2013-01-09 33 views
81

私は単純なwpfデスクトップアプリケーションを作成しています。 UIにはちょうどボタンがあり、.csファイルのようなコードがあります。promiseスタイルのタスクでStartを呼び出すことはできません。例外が来ています

private void Button_Click_2(object sender, RoutedEventArgs e) 
{ 
    FunctionA(); 
} 

public void FunctionA() 
{ 
    Task.Delay(5000).Start(); 
    MessageBox.Show("Waiting Complete"); 
} 

しかし、意外にもラインTask.Delay(5000).Start();が投げているInvalidOperationException

スタート約束スタイルのタスクで呼び出されないことがあります。

なぜこのような理由で助けてもらえますか?

答えて

120

Taskクラスはすでにあなたにそれを与える前にタスクを開始しましたので、あなたはそのエラーを取得しています。 Startは、そのコンストラクタを呼び出すことによって作成したタスクにのみ呼び出す必要があります。作成するときにタスクを開始したくない魅力的な理由がない限り、それを行うべきではありません。すぐに開始したい場合は、Taskを作成して開始するには、Task.RunまたはTask.Factory.StartNewを使用する必要があります。

だから、今私たちはただその厄介者を取り除くことを知っていますStart。コードを実行して、すぐにメッセージボックスが表示されることを確認します.5秒後には表示されません。

まあ、Task.Delayは、5秒で完了するタスクを提供します。スレッドの実行を5秒間停止しません。あなたがしたいことは、そのタスクが終了した後に実行されるいくつかのコードを持つことです。それはContinueWithのためです。これは、与えられたタスクが完了した後にいくつかのコードを実行することを可能にします:

public void FunctionA() 
{ 
    Task.Delay(5000) 
    .ContinueWith(t => 
    { 
     MessageBox.Show("Waiting Complete"); 
    }); 
} 

これは期待どおりに動作します。

我々はまた、より簡単に継続を追加するためにC#5.0のawaitキーワードを活用できます。

public async Task FunctionA() 
{ 
    await Task.Delay(5000); 
    MessageBox.Show("Waiting Complete"); 
} 

ここで何が起こっているかの完全な説明はこの質問の範囲を超えているが、最終結果は方法であり、以前のメソッドと非常によく似た動作をします。メソッドを呼び出すと5秒後にメッセージボックスが表示されますが、メソッド自体はどちらの場合でもすぐに[ほとんど]戻ります。つまり、awaitは非常に強力で、シンプルでわかりやすいメソッドを書くことができますが、それは直接ContinueWithを使って書くのがはるかに難しくて面倒かもしれません。また、エラー処理の扱いを大幅に簡素化し、多くの定型コードを取り出します。

1

private void Button_Click_2(object sender, RoutedEventArgs e) 
{ 
    FunctionA(); 
} 

public async void FunctionA() 
{ 
    await Task.Delay(5000); 
    MessageBox.Show("Waiting Complete"); 
} 
-4

Servyはそうあなたがする残っているすべては(.WAIT())、それを待っている、タスクがすでに開始されている、言ったように:

private void Button_Click_2(object sender, RoutedEventArgs e) 
{ 
    FunctionA(); 
} 
public void FunctionA() 
{ 
    Task.Delay(5000).Wait(); 
    MessageBox.Show("Waiting Complete"); 
} 
+0

タスクに ')(待って'の呼び出しはブロックされますタスクが解決するまで現在のスレッドそれはあなたが何をしたいかほとんど決してありません。 – Jeremy

+0

@Jeremy:あなたが言及した振る舞いに注意する価値はありますが、この場合、彼のFunctionAはすでに現在のスレッドをブロックしていたので、タスクが完了した時点を判断する方法を探していたと思います。待機と非同期(将来の読者のための)の違いを明確にするには、この[リンク](http://stackoverflow.com/questions/9519414/whats-the-difference-between-task-start-wait-and-async-待つ) – Sergiu

関連する問題