Startは、promiseスタイルのタスクでは呼び出されない場合があります。例外が来ています


108

シンプルなwpfデスクトップアプリケーションを作成しています。UIにはボタンと.csファイルのようなコードがあります。

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ます:

Startは、promiseスタイルのタスクでは呼び出されない場合があります。

なぜそれがこのようなものであるかを誰かが助けることができますか?

回答:


171

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

そのため、今ではその厄介な問題を取り除くことがわかっていStartます。コードを実行すると、メッセージボックスがすぐに表示され、5秒後ではないことがわかります。

まあ、Task.Delay5秒で完了するタスクを提供します。スレッドの実行を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直接使用して書くのははるかに困難で面倒です。また、多くのボイラープレートコードを取り除き、エラー処理を大幅に簡素化します。



-4

Servyが言ったように、タスクはすでに開始されているので、あとはタスクを待つだけです(.Wait()):

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

1
Wait()タスクを呼び出すと、タスクが解決されるまで現在のスレッドがブロックされます。それがあなたが起こりたいことではほとんどありません。
ジェレミー

1
@ジェレミー:確かに、あなたが言及した動作に注意を払う価値がありますが、この場合、彼のFunctionAは現在のスレッドを既にブロックしているので、タスクがいつ完了したかを判断する方法を探しているだけだと思いました。Waitとasync(将来の読者向け)の違いを明確にするために、このリンク
Sergiu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.