【问题标题】:Await alternative in .NET 4.0?等待 .NET 4.0 中的替代方案?
【发布时间】:2012-11-02 21:26:10
【问题描述】:
.NET 4.0 中 await 关键字的最佳替代方案是什么?我有一个方法需要在异步操作后返回一个值。我注意到 wait() 方法完全阻塞了线程,从而使异步操作变得无用。在释放 UI 线程的同时运行异步操作有哪些选择?
【问题讨论】:
标签:
c#
.net
task-parallel-library
c#-5.0
【解决方案1】:
您可以使用 yield 协程实现类似 await 的行为,我在非 4.5 代码中使用它。你需要一个 YieldInstruction 类,它是从应该运行异步的方法中检索的:
public abstract class YieldInstruction
{
public abstract Boolean IsFinished();
}
然后你需要一些YieldInstruction 的实现(即处理任务的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);
}
}
在开发 WPF 或 WinForms 应用程序时,如果您在正确的时间更新协程,您还可以避免任何 Invoke 调用。你也可以扩展这个想法,让你的生活更轻松。示例:
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
}
【解决方案2】:
我认为你的基本选择是
最简单的方法可能是安装 Async CTP。据我所知,许可证允许商业用途。它对编译器进行了修补,并附带一个 150kb 的 dll,您可以将其包含到您的项目中。
您可以使用Task 和.ContinueWith()。但这意味着,您必须在异常处理和流量控制方面付出一些努力。
任务是一种功能结构。这就是为什么ContinueWith() 不能很好地与诸如for 循环或try-catch 块之类的命令式结构混合使用。因此引入了async和await,以便编译器帮助我们。
如果您无法获得编译器的这种支持(即您使用 .Net 4.0),那么最好的办法是将TAP 与功能框架一起使用。 Reactive Extensions 是一个非常好的处理异步方法的框架。
只需在 Google 上搜索“响应式扩展任务”即可开始使用。