2013-09-07 10 views
12

Task.Delay()が期待どおりに動作しないか、まあまあ、私は何をすべきか理解できません。私はTaskをC#で頭に入れようとしています。私の実装ではThreadを置き換える方法を教えています。Task.Delay()が期待どおりに動作しない

私は何をしようとしているが、このようなものです:

    • 印刷しながらライン秒
    • 待ち、
    • 条件が満たされた場合、終了ループ、そうでなければループを維持する

私はスレッドでうまく実装されているが、クールな子供たちはすべて私がタスクを使用する必要があり、スレッドに触れてはいけないと言います。私はこれを実行すると

[Test] 
    public void ChattyTask() 
    { 
     var chattyTask = new Task(ChattyWriter); 
     chattyTask.Start(); 
     chattyTask.Wait(); 
    } 

    public void ChattyWriter() 
    { 
     int count = 0; 
     while (true) 
     { 
      var message = String.Format("Chatty Writer number {0}", count); 
      Trace.WriteLine(message); 
      count++; 
      Task.Delay(1000); 

      if (count >= 20) 
      { 
       break; 
      } 
     } 
    } 

、テストは私と同じように20秒ではない、ミリ秒で終了 -

だから私はこれを持っているコードの(物事を試すために、この単なる便利な方法[Test]を無視)期待する。 Task.Delay()Thread.Sleep()に置き換えると、すべて正常に動作し、1秒に1回プリントアウトします。私はChattyWriter()asyncawaitを追加しようとしているだけでなく、それは1秒の遅延を追加しなかった、それだけの代わりに私が間違っているのは何20

の一行だけを印刷しますか?

おそらく、私のプロジェクトは外部API(RESTful)で動作し、いくつかのタスクを実行するよう要求した後、タスクが完了したかどうかを確認するためにAPIをポーリングする必要があります。外部タスクは長時間実行することができます:1-15分。だから私は完了を確認する間にいくつかの遅延が必要です。そして、複数の外部タスクで実行される多くの異なる並行プロセスが存在する可能性があります。ポーリング時にThread.Sleep()を使用すると、同じ理由のために同じThreadの他のプロセスがブロックされることを理解しています。

答えて

26

Task.Delay

Task.Delay(1000); 

を置き換えることができますあなたは待つ必要がどのTaskオブジェクトを返します。そうしないと、すぐに次のコードが実行されます。あなたのメソッドをasyncと宣言する必要があります。それでは待つことができますTask.Delay

public async Task ChattyWriter() 
{ 
    int count = 0; 
    while (true) 
    { 
     var message = String.Format("Chatty Writer number {0}", count); 
     Trace.WriteLine(message); 
     count++; 
     await Task.Delay(1000); 
      ... 
    } 
} 

何とかあなたの呼び出しスレッドを中断する必要があります。ユニットテストは終了し、バックグラウンドスレッドも終了します。しかし、このメソッドをUIから呼び出すと、UIはブロックされません。

Waitを非同期メソッドで呼び出すと、デッドロックが発生します。詳細については、hereを参照してください。

+0

私はこれを試してみました。そして、最初の行だけが印刷され、その直後に完了しました。 – trailmax

+2

おそらく、あなたのメインスレッド(テストルーチン)は動作し続けることができ、プログラムが終了するので、残りの部分は表示されない可能性があります。 UIボタンからスレッドを開始しますか?UIはまだ応答します。 – slfan

+0

+1それは正しい解決策です。 – GolfWolf

16

Task.Delay(1000);は、1秒後に完了する非同期タスクを作成しますが、現在のメソッドの実行は並行して継続されます。最初のタスクが完了するのを待つために

、あなたが

Task.Delay(1000).Wait(); 
+0

OMGを試してみては、このような小さなディテールを逃しました。ありがとうございました! – trailmax

+3

@trailmaxしかし、これは1秒間何もしない新しいタスクを作成します。はるかに良いアプローチは単にThread.Sleep(1000)を呼び出すことです。 – Alberto

+0

@ trailmax私の記事で 'Task.Delay'が機能しなかった理由を説明している間に、より効率的な[slfanの答え](http://stackoverflow.com/a/18672852/390819)に記載されているアプローチを検討してください。 – GolfWolf

1

Task.Delay()は実際にタスクを作成するので、タスクを待つだけです。

この

 public static void ChattyWriter() 
    { 
     int count = 0; 
     while (true) 
     { 
      var message = String.Format("Chatty Writer number {0}", count); 
      Console.WriteLine(message); 
      count++; 
      var t = Task.Delay(1000); 
      t.Wait(); 

      if (count >= 20) 
      { 
       break; 
      } 
     } 
    } 
+3

Task.DelayがTaskを返す主な理由は、そのタスクに対してwaitを呼び出すことができることです。あなたの答えは@ w0lfと同じです – slfan

関連する問題