70

次のように、いくつかの並列タスクを開始します。

var tasks =
    Enumerable.Range(1, 500)
    .Select(i => Task.Factory.StartNew<int>(ProduceSomeMagicIntValue))
    .ToArray();

そしてそれらに参加します

Task.WaitAll(tasks);

この最後の行で、 の下に青い波線のマーカーがtasks表示され、警告メッセージが表示されます。

Task[] から Task[] への共変配列変換
書き込み操作で実行時例外が発生する可能性があります。

このメッセージが表示される理由は理解できましたが、それを回避する方法はありますか? (たとえば、Task.WaitAll()? の一般的なバージョンのように)

4

4 に答える 4

33

Task.WaitAll のジェネリック メソッドは、すべての Task が同じ型を返さなければならないことを意味し、有用性が非常に制限されます。そのようなものを書くことは手動で行うことができます (Bas Brekelmans の回答を参照) が、これは多くの作業なしでは ContinueWith またはキャンセルを許可しません。

他に配列を使用していない場合の簡単な解決策は次のとおりです。

  .ToArray<Task>();
于 2012-04-06T13:30:54.500 に答える
29

警告があっても安全な操作であると確信していますが、本当にそれを回避したい場合は、独自の実装を作成するよりも良いオプションは、tasksパラメーターを必要な型に変換することです。

Task.WaitAll(tasks.Cast<Task>().ToArray())

これにより、青い波線がなくなり、tasks変数をジェネリックに保つことができ、最終的に不要な新しい恐ろしいコードを大量に作成する必要がなくなります。

于 2012-04-06T14:20:46.293 に答える
6

これを行うための拡張メソッドを作成できます。

WaitAll の正確な実装はわかりませんが、すべてのアイテムが完了するまで待機すると仮定できます。

static class TaskExtensions
{
    public static void WaitAll<T>(this Task<T>[] tasks)
    {
        foreach (var item in tasks)
        {
            item.Wait();
        }
    }
}

次に、現在のコードから呼び出します。

tasks.WaitAll();

編集

実際の実装はもう少し複雑です。かなり長いため、この回答からコードを省略しました。

http://pastebin.com/u30PmrdS

これを変更して、一般的なタスクをサポートできます。

于 2012-04-06T13:36:03.543 に答える