.NET 4.0 の await キーワードに代わる最良の方法は何ですか? 非同期操作の後に値を返す必要があるメソッドがあります。wait() メソッドがスレッドを完全にブロックしているため、非同期操作が役に立たないことに気付きました。UI スレッドを解放しながら非同期操作を実行するには、どのようなオプションがありますか?
2 に答える
あなたの基本的なオプションは
Task
と_.ContinueWith()
- 非同期CTPと
async
/の使用await
- リアクティブ拡張機能の使用
最も簡単な方法は、おそらく Async CTP をインストールすることです。私の知る限り、ライセンスは商用利用を許可しています。コンパイラにパッチを適用し、プロジェクトに含めることができる 150kb の dll が付属しています。
Task
とを使用できます.ContinueWith()
。ただし、これは、例外処理とフロー制御に多少の努力が必要であることを意味します。
タスクは機能的な構造です。そのため、ループやブロックContinueWith()
などの命令型構造とうまく混合できません。したがって、コンパイラが私たちを助けることができるように導入されました。for
try-catch
async
await
コンパイラのサポートを利用できない場合 (つまり、.Net 4.0 を使用している場合) は、TAPを機能的なフレームワークと一緒に使用することをお勧めします。Reactive Extensionsは、非同期メソッドを処理するための非常に優れたフレームワークです。
開始するには、「リアクティブ拡張タスク」をグーグルで検索してください。
await
コルーチンのような動作を実装できますyield
。私はこれを 4.5 以外のコードで使用しています。YieldInstruction
非同期で実行する必要があるメソッドから取得されるクラスが必要です。
public abstract class YieldInstruction
{
public abstract Boolean IsFinished();
}
YieldInstruction
次に、 (タスクを処理する ae )のいくつかの実装が必要であり、TaskCoroutine
この方法で使用します(疑似コード):
public IEnumerator<YieldInstruction> DoAsync()
{
HttpClient client = ....;
String result;
yield return new TaskCoroutine(() => { result = client.DownloadAsync(); });
// Process result here
}
次に、命令の実行を処理するスケジューラが必要です。
for (Coroutine item in coroutines)
{
if (item.CurrentInstruction.IsFinished())
{
// Move to the next instruction and check if coroutine has been finished
if (item.MoveNext()) Remove(item);
}
}
Invoke
WPF または WinForms アプリケーションを開発する場合、適切なタイミングでコルーチンを更新していれば、呼び出しを回避することもできます。また、アイデアを拡張して、生活をさらに楽にすることもできます。サンプル:
public IEnumerator<YieldInstruction> DoAsync()
{
HttpClient client = ....;
client.DownloadAsync(..);
String result;
while (client.IsDownloading)
{
// Update the progress bar
progressBar.Value = client.Progress;
// Wait one update
yield return YieldInstruction.WaitOneUpdate;
}
// Process result here
}