2015-10-15 8 views
5
私は SynchronizationContext上のデッドロックのような何かを明らかに欠落しなければならない

を待つが、それはなぜ起こるか私は見ていない、と私はそれを避けることができる方法を理解していない/非同期でハングTask.WaitAllは...タスク

したがって、アプリケーションはAzure WorkerRoleです(基本的には、私が理解する限り、UIのない​​通常のWindowsアプリです)。アプリケーションでは、私はタスクの数の並列実行、そして私のコードの概略的なバージョンにしようとしていますが、このです:

private async Task DoJob() 
{ 
    await SomeIoOperation(); 
} 


public void MethodExecutedByWorkerRoleInAnInfiniteLoop() 
{ 
    Log("Start"); 
    Task.WaitAll(DoJob(), DoJob(), DoJob()); 
    Log("End"); 
} 

ここでの私の考えは、私たちがここでデフォルトSynchronizationContextで動作しているということですので、我々は避けるべきです私たちがASP.NETなどの同様の状況で持つデッドロックです。

ただし、時には実行がハングアップ - 開始が記録されます。作業者ロールを再開するまで、終了日数は日数ではありません。当然のことながら、DoJobはそれほど長い間走っているわけではありません。奇妙なことに、これは作業員の役割が開始された直後には起こりません。通常の操作でハングするまで数日か数週間かかります。

私はコードをあまりにも単純化することができます - おそらく正確に何が起こるのが重要でしょうかSomeIoOperation - これはSynchronizationContextに関連する明らかなものです。

Will SomeIoOperation.ConfigureAwait(false)?問題が修正されたために動作しているかどうかわからないか、最終的に数日後にハングアップするため、テストすることすらできません。

アイデア?

+1

この記事では、原因について啓発します。http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html – Gusdor

+2

「Log(SynchronizationContext.Current);」に追加し、ifそれは 'nullではない'あなたが 'SynchronizationContext'に問題があることを知っているでしょう。 – i3arnon

+0

'DoJob'は常に呼び出しコンテキストに同期します。 'SomeIoOperation'がどのコンテキストを使用するかは重要ではありません。 – Gusdor

答えて

8

SynchronizationContextでは、デッドロックが発生します。

public async Task MethodExecutedByWorkerRoleInAnInfiniteLoop() 
{ 
    Log("Start"); 
    await Task.WhenAll(DoJob(), DoJob(), DoJob()); 
    Log("End"); 
} 

を、すべてが動作します: だけWaitAllの代わりにWhenAllを使用しています。

+1

このメソッドはループで実行されます。呼び出し元は、メソッドがいつ完了したかを知りたいと思うでしょう。 IMO、このリビジョンは 'Task'を返すべきです。 – Gusdor

+0

ありがとうございます。私はタスク上の空白を変更することを忘れています。 –

+0

しかし、私のループでは、 'MethodExecutedByWorkerRoleInAnInfiniteLoop()。Wait()'を実行する必要があります。私が知る限り、 'Microsoft.WindowsAzure.ServiceRuntime'には' RoleEntryPoint'の非同期バージョンはありませんので、どこでも 'MethodExecutedByWorkerRoleInAnInfiniteLoop'を待つことはできません。 –

関連する問題