87

私は非同期プログラミングが初めてなので、いくつかの非同期サンプル コードを試した後、単純な非同期コードを作成することを考えました。

簡単な Winform アプリケーションを作成し、フォーム内に次のコードを記述しました。しかし、それは機能していません

private Task<string> methodAsync() {
    Thread.Sleep(10000);
    return "Hello"; //Error: Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>'
}

private async void button1_Click(object sender, EventArgs e)
{
    string s = await methodAsync();
    MessageBox.Show(s);
}

誰かここに光を当ててくれませんか..

4

5 に答える 5

143

リストされているメソッドの戻り値の型は ですTask<string>。を返そうとしていますstring。それらは同じではなく、 string から への暗黙的な変換もないTask<string>ため、エラーが発生します。

これを、コンパイラによってasync戻り値が自動的に a にラップされるメソッドと混同している可能性があります。Task現在、そのメソッドは非同期メソッドではありません。あなたはほぼ間違いなくこれを行うつもりでした:

private async Task<string> methodAsync() 
{
    await Task.Delay(10000);
    return "Hello";
}

主な変更点は 2 つあります。まず、メソッドは としてマークされますasync。これは、戻り値の型が でラップされTask、メソッドがコンパイルされることを意味します。次に、ブロッキング待機を行いたくありません。原則として、awaitモデルを使用するときは、できる限り待機をブロックしないようにしてください。 Task.Delay指定されたミリ秒数後に完了するタスクです。そのタスクをawait-ing することで、その時間の非ブロッキング待機を効果的に実行しています (実際には、メソッドの残りの部分はそのタスクの継続です)。

を使用せずに 4.0 の方法を使用awaitしたい場合は、次のようにします。

private Task<string> methodAsync() 
{
    return Task.Delay(10000)
        .ContinueWith(t => "Hello");
}

最初のバージョンは多かれ少なかれこれに似たものにコンパイルされますが、awaitここでは利用していないエラー処理やその他の機能をサポートするために、いくつかの追加のボイラープレート コードが含まれています。

Thread.Sleep(10000)しばらく待つ方法ではなく、長時間実行されるメソッドの単なるプレースホルダーであることが本当に意図されている場合は、現在のコンテキストではなく、別のスレッドで作業が行われるようにする必要があります。これを行う最も簡単な方法は次のTask.Runとおりです。

private Task<string> methodAsync() 
{
    return Task.Run(()=>
        {
            SomeLongRunningMethod();
            return "Hello";
        });
}

または、より可能性が高い:

private Task<string> methodAsync() 
{
    return Task.Run(()=>
        {
            return SomeLongRunningMethodThatReturnsAString();
        });
}
于 2013-02-02T02:33:28.857 に答える