2013-02-02 8 views
40

「System.Threading.Tasks.Task 」に変換できません。私は、非同期プログラミングに新しいですので、いくつかの非同期サンプル・コードを通過した後、私はシンプルな非同期コードを書くと考え が暗黙的にタイプ「string」が

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

は、誰かが方法の記載された戻り値の型がTask<string> ..ですここ

答えて

68

をいくつかの光を入れてくださいでした。あなたはstringを返そうとしています。それらは同じではなく、文字列からTask<string>への暗黙的な変換もないため、エラーです。

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

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

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

あなたがそれを行うの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"; 
     }); 
} 

以上の可能性:

@Servyで指摘したように asyncの問題の使用を越えて
private Task<string> methodAsync() 
{ 
    return Task.Run(()=> 
     { 
      return SomeLongRunningMethodThatReturnsAString(); 
     }); 
} 
+1

どのように私は明示的に '' Task'でSTRING'をラップすることができますか?ORは、呼び出されているメソッド(この場合はmethodAsync)で 'async'と' await'を使わずに 'Task'または' Task 'を返す方法はありませんか? – dotNETbeginner

+0

@dotNETbeginnerいいえ –

+1

@Aniketいいえ、間違っています。タスクに文字列を明示的にラップする方法はたくさんあります。私は解を編集します。 – Servy

12

、他の問題は、明示的にする必要があることですTask.Resultを呼び出してTask<T>からTを取得します。 Resultプロパティは非同期コードをブロックするため、注意深く使用する必要があります。

試してみてください。

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

これは強く推奨されないかもしれませんが、 'catch 012 'の中に' Task 'コンテンツを戻したいという事例がありました。私は 'await'できず、' .ToString() 'は間違った結果を出しました。これは法案に適合します。 – doubleJ

13

使用FromResult方法

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

これはまさに私が必要としていたものです。 –

+1

ベストアンサーに選ばれました。ポイントへ。 – BaBu

+1

この回答は、のタスクで定義されたインターフェイスを実装する最良の方法です –

関連する問題