2012-11-14 98 views
10

什么是.NET 4.0中await关键字的最佳选择?我有一个方法需要在异步操作后返回一个值。我注意到wait()方法完全阻塞了线程,从而导致异步操作无用。在仍然释放UI线程的同时运行异步操作的选项有哪些?在.NET 4.0中等待替代?

+1

使用await,但以正确的方式,我猜。你有一些代码? – lboshuizen

+3

将VS2012与C#5.0一起使用,而将.NET 4.0作为目标是否可以接受?请参阅[在.net 4上使用async-await](http://stackoverflow.com/questions/9110472/using-async-await-on-net-4) – CodesInChaos

+0

@CodesInChaos对于同事,不:)。 – Dante

回答

4

我觉得你的基本选项

最简单的方法可能是安装异步CTP。据我所知,许可证允许商业用途。它修补了编译器,并带有一个150KB的dll,你可以将它包含到你的项目中。可以使用Task.ContinueWith()。但这意味着,你必须采取一些措施来处理和控制流量。

任务是一个功能结构。这就是为什么ContinueWith()不能与命令性结构如for环或try-catch块混合良好。因此asyncawait得到了介绍,以便编译器可以帮助我们。

如果你不能得到编译器的支持(即使用.Net 4.0),最好的方法是将TAP与功能框架一起使用。 Reactive Extensions是一个处理异步方法的非常好的框架。

刚刚谷歌的“反应扩展任务”开始。

1

你可以用yield协程来实现类似await的行为,我在非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); 
    } 
} 

在开发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 
}