2

WinForm プロジェクトで長時間実行される操作にタスクの継続を使用しています。

var task1 = Task.Factory.StartNew(() => DoSomeWork());

var task2 = task1.ContinueWith(result => DoSomeMoreWork(), TaskContinuationOptions.OnlyOnRanToCompletion);

var task3 = task2.ContinueWith(result => DoFinalWork(), TaskContinuationOptions.OnlyOnRanToCompletion);

task2 で実行される DoSomeMoreWork() 関数でいくつかの条件が満たされた場合にのみ、task3 に進みたいと考えています。これはどのように行うことができますか?

4

2 に答える 2

1

もう1つのオプションは、task2とtask3をネストされたタスクに変換し、条件が満たされた場合にのみそれらを実行することです。

DoSomeMoreWorkがこれを行うためにtrueを返すと仮定すると、次のように書くことができます。

        var task1 = Task.Factory.StartNew(DoSomeWork);
        var task2 = task1.ContinueWith(result =>
            {
                if (DoSomeMoreWork())
                {
                    Task.Factory.StartNew(DoFinalWork, TaskCreationOptions.AttachedToParent);
                }
            }, TaskContinuationOptions.OnlyOnRanToCompletion);

AsyncCTPまたは.NET4.5(どちらもGo Liveライセンスを持っていると思います)を使用できる場合は、継続をasync / awaitに置き換えて、よりクリーンなコードを得ることができます。

ワーカー関数を非同期を使用するように変換すると、コードは同期バージョンとほぼ同じように明確になります。

    private static async void WorkAsync()
    {
        await DoSomeWork();
        if (await DoSomeMoreWork())
        {
            await DoFinalWork();
        }
    }

    private static async Task DoFinalWork()
    {
        Console.WriteLine("Completed");
    }

    private static async Task<bool> DoSomeMoreWork()
    {
        Console.WriteLine("Some More");
        return true;
    }

    private static async Task DoSomeWork()
    {
        Console.WriteLine("Some");
    }

メソッドからタスクを返したくない場合は、次のコードを使用できます。

    private static async void WorkAsync()
    {
        await Task.Run(()=>DoSomeWork());
        if (await Task.Run(()=>DoSomeMoreWork()))
        {
            await Task.Run(()=>DoFinalWork());
        }
    }
于 2012-06-08T13:00:37.200 に答える
1

MSDNから

ユーザー定義の値を先行詞からResultプロパティの継続に渡すことができるため、先行詞の出力を継続の入力として使用できます。

したがって、1つの方法はtask3にあります。作業を行う前に、task2の結果を確認してください。

var task2 = task1.ContinueWith(result => DoSomeMoreWOrk(), TaskContinuationOptions.OnlyOnRanToCompletion);
var task3 = task2.ContinueWith(x => DoFinalWork(x.Result));

task2から返された結果によって、task3で何が起こるかが決まります。

編集 別の解決策は、操作内で特定の条件が満たされない場合にtask2をキャンセルすることです。その場合、継続タスクはスケジュールされていません。

MSDNから

先行がキャンセルされた場合に継続が実行されないようにするには、継続を作成するときにNotOnCanceledオプションを指定します。

したがって、task3の定義は次のようになります

var task3 = task2.ContinueWith(result => DoFinalWork(), TaskContinuationOptions.NotOnCancelled);
于 2012-06-08T09:42:14.673 に答える