我有一个类抽象执行远离我的WPF MVVM视图模型后台线程的长时间运行方法。我也有这个类接口和IoC注入我的大多数视图模型。.NET任务/ TPL测试和嘲讽? (或不正确的用法?)
private void LoadStuff()
{
ActionManager.StartAsyncTask(() => { // Load stuff from database here });
}
而且在我的一些XAML我直接绑定到IsBusy属性:
public interface IAsyncActionManager : INotifyPropertyChanged
{
/// <summary>
/// Sets and gets the IsBusy property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
bool IsBusy { get; }
Task StartAsyncTask(Action backgroundAction);
}
我的视图模型以各种方式,如使用该类
<Grid Cursor="{Binding ActionManager.IsBusy, Converter={Converters:BusyMouseConverter}}">
不管怎样 - 现在你有背景,我正在尝试做一些更花哨的事:
private Task _saveChangesTask;
public void SaveChanges()
{
if (_saveChangesTask != null && _saveChangesTask.Status != TaskStatus.Running)
return;
_saveChangesTask = ActionManager.StartAsyncTask(() =>
{
// Save stuff here - slowly
});
}
这是简化的,因为我也通过一个Command对象把它连接起来,WPF在它的视图中使用了CanExecute等,但是这个任务的“缓存”使得保存操作不会运行两次。
现在,解决问题,我想单元测试这个逻辑 - 我该怎么做? 我试过在我的测试中使用TaskCompletionSource,但我无法让我的任务进入“正在运行”状态......?
var tcs = new TaskCompletionSource<object>();
// tcs.Task.Status is now WaitingForActivation
// tcs.Task.Start(Synchronous.TaskScheduler); // Doesn't work - throws an Exception.
A.CallTo(() => mockAsyncActionManager.StartAsyncTask(A<Action>._, A<Action<Task>>._)).Returns(tcs.Task);
任何人有任何线索?我可以这样做吗?
我有一个想法,我错误地使用TPL - 我不应该依赖任务状态 - 但不知道如何以另一种方式实现类似的事情(建议欢迎)。
干杯,
您的保存任务有轻微的竞争条件。您应该在支票和作业周围锁定一个锁。从技术上讲,两个线程可以检查,得到空值,然后运行任务两次,但只分配一个(第二个任务将覆盖第一个任务)。 – casperOne 2012-02-28 17:54:51