1

各メソッドが非同期に実行される、つまりタスクを返すクラスがありますが、それでも各メソッドは前の呼び出しの完了を待つ必要があります。

続きですよね?

ただし、タスクの継続は、別のタスクではなく、パラメーターでデリゲート (アクション) を取ります。

私はさまざまなことを試しましたが、それを機能させるためにできる最善のことは、次の(私にとっては非常に複雑な)コードです:

    private Task QueueTask(Func<Task> futureTask)
    {
        var completionSource = new TaskCompletionSource<int>();

        _lastTask.ContinueWith(async t =>
        {
            try
            {
                await futureTask();

                completionSource.SetResult(0);
            }
            catch (Exception ex)
            {
                completionSource.SetException(ex);
            }
        });

        _lastTask = completionSource.Task;

        return _lastTask;
    }

ここで _lastTask は、私のクラスのプライベート メンバーです。すべての呼び出しは UI スレッドから来ているので、最後のタスクを保持して継続します。

前述したように、このコードは非常に複雑です。より良い提案はありますか?

4

1 に答える 1

2

私には、あなたが間違った質問をしているように思えます。このようなタスクのキューは、珍しい要件です。私たちはあなたが解決しようとしている実際の問題について何も知らないので、より良いアプローチを提案することはできません.

ContinueWith動的な並列処理を目的としているため、コードにはあまり適合しません。asyncただし、ContinueWithペアリングを使用しUnwrapて、 の動作をエミュレートすることができます (が現在のコンテキストとawaitどのように相互作用するかを無視する場合)。await

したがって、タスク ソリューションのキューを次のように単純化できます。

private Task QueueTask(Func<Task> futureTask)
{
    _lastTask = _lastTask.ContinueWith(t => futureTask()).Unwrap();
    return _lastTask;
}

ただし、おそらくより良い解決策があります。キューの目的が排他的アクセスを提供することである場合は、a のSemaphoreSlim方が自然です。何らかの理由で実際にキューが必要な場合は、Dataflow メッシュの使用を検討してください。

于 2013-07-09T16:58:06.467 に答える