2013-07-05 11 views
5

私は以下のような作業をしています。Task.waitとcontinueWIth

var task = Task<string>.Factory.StartNew(() => longrunningmethod() 
    .ContinueWith(a => 
      longrunningmethodcompleted((Task<string>)a, 
        TaskScheduler.FromCurrentSynchronizationContext()))); 

task.Wait(); 

私のタスクはlongrunningメソッドを呼び出し、完了後に完了メソッドを呼び出します。 私のlongrunningmethodの中で私はThread.Sleep(30000)によって遅れています。 Task.waitシステムを使用するとシステムがハングし、longrunningmethodcompletedメソッドが呼び出されません。私がTask.waitを使わないと、すべてがうまくいく。

+0

私はデッドロックのような音ですが、シングルスレッド環境でこれをやっていますか?私はこれがWindows Phone開発でこれまでに起こっているのを見ました。 ([関連](http://stackoverflow.com/questions/8277291/continuation-tasks-hanging-when-using-limitedconcurrencyleveltaskscheduler) –

答えて

12

あなたのコンテキストがUIコンテキストであることが強く疑われます。

この場合、longrunningmethodcompletedに現在のSynchronizationContextで実行するように指示しているため、デッドロックが発生しています。

次に、Waitを呼び出してそのコンテキストをブロックしています。 Waitでブロックされているスレッドで実行する必要があるため、継続は完了しません。

これを修正するには、そのコンテキストで継続してWaitを使用することはできません。私はlongrunningmethodcompleted必要 UIスレッド上で実行し、その解決策はContinueWithに呼び出してWaitへの呼び出しを交換することであると仮定しています:

var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
var task = Task<string>.Factory.StartNew(() => longrunningmethod() 
    .ContinueWith(a => 
     longrunningmethodcompleted((Task<string>)a, 
     ui); 
task.ContinueWith(..., ui); 

をそれとも、あなたはVS2012にアップグレードして使用することができますasync/await 、これはあなたがこのような非常にクリーンなコードを書くことができます:

var task = Task.Run(() => longrunningmethod()); 
await task; 
longrunningmethodcompleted(task); 
+0

ありがとうございました。ありがとうございました。はい、それは動作します。vs2010を使用していますが残念ながらvs2012.ISにアップグレードできません。タスクが完了するまで待つようにUIスレッドを作成できます。 – user2107843

+0

あなたの唯一のオプションは、タスクスケジューラなしで継続*を実行するか、残りの作業を続行することです。はい、現実世界のどの非同期シナリオでも非常に厄介です。そして、これが「非同期」が発明された理由です。 –

-1

Thread.Sleep(nnn)がブロックしています。使用Task.Delay(NNN)と待っています:

await Task.Delay(30000); 

追加する編集:ちょうどタグは、C#4。これはC#5と新しい非同期サポートを待つ必要と言う指摘しました。真剣に、非同期とタスクを実行している場合は、アップグレードする必要があります。

+0

C#4。0はお待ちください – konkked

0

は、まあ、それは実際の非同期アクションが何であるかを見ることなく、あなたのコードに問題があるものを伝えるのは難しいですが、私が知っているすべては、MSDN waits for the task to be completedに応じています。現在のSynchronizationContextを使用しようとしているため、あなたのアクションブロックは可能でしょうか?

私が求めています理由は、あなた

  1. スタートタスクタスクは
  2. タスクが
  3. タスクをしようとする現在のSynchronizationContextを継続しようとする(タスクを継続している)を完了するために
  4. 待ち待ち時間が
  5. を完了した後に糸を取る予定のメインスレッド
  6. タスクを取得しかし、完了するために、現在のタスクを待っている待って(デッドロック)



あなたのプログラムがThread.Sleep(seconds)で動作する理由は、制限時間が過ぎるとスレッドが続行されるからです。

+0

チャールズありがとうありがとう私は今デッドロックが発生したと理解しています。私がTask.waitを必要とする理由は、UIスレッドをwait.isメソッドをメインスレッドがタスクが完了するまで待つことができる方法です。 – user2107843

関連する問題