私は、WPF MVVMビューモデルからバックグラウンドスレッドで長い実行メソッドを抽象化するクラスを持っています。私はまた、このクラスをインターフェイスし、ほとんどのビューモデルにIoCを注入しました。.NETタスク/ TPLテストと嘲笑? (または間違った使用ですか?)
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);
}
マイビューモデルのようなさまざまな方法でこのクラスを使用します。
private void LoadStuff()
{
ActionManager.StartAsyncTask(() => { // Load stuff from database here });
}
そして、私のXAMLのいくつかで、私はIsBusyプロパティに直接バインド:とにかく
<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
});
}
私もそれはWPFがCanExecuteなどとのビューで使用していますが、保存するアクションが二度実行されないように、タスクのこの「キャッシュ」であるCommandオブジェクトを経由してフックアップ持っているとして、これは簡略化されています。
は今、問題になって、私はこのロジックユニットテストしたい - どのように私はそうするのですか? テストで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を使用しているという考え持っている - 私は、タスクのステータスに頼るべきではないことを - しかし、(提案は歓迎します)別の方法で同様のことを達成する方法がわからないし。
乾杯、
あなたのセーブ・タスクにはマイナーな競合状態があります。あなたは小切手と割り当ての周りにロックを配置する必要があります。技術的には、2つのスレッドがチェックし、ヌルを取得してからタスクを2回実行しますが、1つだけ割り当てます(2番目のタスクは最初のタスクを上書きします)。 – casperOne