web-dev-qa-db-ja.com

型 'string'を 'System.Threading.Tasks.Task <string>'に暗黙的に変換できません

私は非同期プログラミングが初めてなので、いくつかの非同期サンプルコードを調べた後、簡単な非同期コードを書くことを考えました

簡単な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);
}

誰かがここに光を当ててください。

57
dotNETbeginner

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

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

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

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

awaitを使用せずに4.0の方法を好む場合、これを行うことができます。

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();
        });
}
102
Servy

FromResultメソッドを使用

public async Task<string> GetString()
{
   System.Threading.Thread.Sleep(5000);
   return await Task.FromResult("Hello");
}
34
Jaswant Agarwal

@Servyによって指摘されたasyncの問題のある使用を超えて、他の問題は、Task.Resultを呼び出してTask<T>からTを明示的に取得する必要があることです。 Resultプロパティは非同期コードをブロックするため、注意して使用する必要があることに注意してください。

試してください:

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