2

TestAwaitTaskArrayAsync() は、コード内の複数の場所から呼び出すことができます。次の呼び出しで taskArray の実行が開始される前に、taskArray の実行をロックし、すべてのタスクが完了するまで非同期で待機する必要があります。コードは次のとおりです。

private async Task TestAwaitTaskArrayAsync()
        {
            Task[] taskArray;
            lock (_lock_taskArray)
            {
              taskArray = new Task[]
              {
                Task.Run(() =>
                {
                    SomeMethod1();
                }),
                Task.Run(() =>
                {
                    SomeMethod2();
                })
              };
            }
            await Task.WhenAll(taskArray);
        }

ロックでの待機は許可されていないため、必要に応じてAsyncLockを使用できますが、シンプルに保つようにしてください。このコードは正しく、スレッドセーフですか? await Task.WhenAll(taskArray); かどうかはわかりません。ロックの外側にある可能性がありますが、代わりに AsyncLock を使用する必要がありますか?

4

1 に答える 1

7

タスクの作成は非常に高速で、何とも競合しないため、使用しているロックはほとんど効果がありません。非同期設定で相互排除を実現する方法は、SemaphoreSlimクラスを使用することです。Task-async パターンをサポートするロックです。

    SemaphoreSlim sem = new SemaphoreSlim(1);
    private async Task TestAwaitTaskArrayAsync()
    {
        await sem.WaitAsync();
        try {
         Task[] taskArray = new Task[]
           {
             Task.Run(() =>
             {
                 SomeMethod1();
             }),
             Task.Run(() =>
             {
                 SomeMethod2();
             })
           };
         }
         await Task.WhenAll(taskArray);
        }
        finally { sem.Release(); }
    }

同期的な方法では、これは簡単だったでしょう:

lock (_lock_taskArray)
 Parallel.Invoke(() => SomeMethod1(), () => SomeMethod2());

終わり。

お好みでご利用も可能AsyncLockです。これにより、コンストラクトを使用しusingてロックを確実に解放できるようになります。

于 2013-10-20T09:54:54.640 に答える