如何C#5.0的异步等待功能从TPL有什么不同? [英] How does C# 5.0's async-await feature differ from the TPL?

查看:162
本文介绍了如何C#5.0的异步等待功能从TPL有什么不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有看到.NET 4.0的的任务并行库。举个例子来说,埃里克利珀的code <一个href=\"http://blogs.msdn.com/b/ericlippert/archive/2010/10/29/asynchronous-programming-in-c-5-0-part-two-whence-await.aspx\">from这里:

I don't see the different between C#'s (and VB's) new async features, and .NET 4.0's Task Parallel Library. Take, for example, Eric Lippert's code from here:

async void ArchiveDocuments(List<Url> urls) {
    Task archive = null;
    for(int i = 0; i < urls.Count; ++i) {
        var document = await FetchAsync(urls[i]);
        if (archive != null)
            await archive;
        archive = ArchiveAsync(document);
    }
}

看来,的await 关键词是服务两种不同的目的。第一次出现( FetchAsync )似乎意味着,的如果这个值被用来以后的方法和它的任务未完成,等待它继续之前完成。的第二个实例(归档)似乎意味着,的如果这个任务还没有完成,等待< STRONG>现在,直到它完成。的如果我错了,请大家指正。

It seems that the await keyword is serving two different purposes. The first occurance (FetchAsync) seems to mean, "If this value is used later in the method and its task isn't finished, wait until it completes before continuing." The second instance (archive) seems to mean, "If this task is not yet finished, wait right now until it completes." If I'm wrong, please correct me.

不能只是​​很容易被写成这样?

Couldn't it just as easily be written like this?

void ArchiveDocuments(List<Url> urls) {
    for(int i = 0; i < urls.Count; ++i) {
        var document = FetchAsync(urls[i]);       // removed await
        if (archive != null)
            archive.Wait();                       // changed to .Wait()
        archive = ArchiveAsync(document.Result);  // added .Result
    }
}

我已经更换了第一个等待 Task.Result ,其中实际需要的值,第二个等待 Task.Wait(),其中等待实际发生。该功能是(1)已经实施,而(2)更接近语义什么在$实况C $角

I've replaced the first await with a Task.Result where the value is actually needed, and the second await with Task.Wait(), where the wait is actually occurring. The functionality is (1) already implemented, and (2) much closer semantically to what is actually happening in the code.

我不明白,一个异步方法被改写为一个状态机,类似于迭代器,但我也没有看到什么带来的好处。任何code,需要另一个线程来操作(如下载)仍然需要另一个线程,任何code,它不(如从文件中读取)仍然可以利用TPL只有一个工作单个线程。

I do realize that an async method is rewritten as a state machine, similar to iterators, but I also don't see what benefits that brings. Any code that requires another thread to operate (such as downloading) will still require another thread, and any code that doesn't (such as reading from a file) could still utilize the TPL to work with only a single thread.

我显然失去了一些东西在这里巨大;任何人可以帮助我理解这一点更好?

I'm obviously missing something huge here; can anybody help me understand this a little better?

推荐答案

我觉得误会就出现在这里:

I think the misunderstanding arises here:

这似乎的await关键字提供两个不同的目的。第一次出现(FetchAsync)似乎是说,如果这个值在方法以后使用它的任务还没有完成,等待它继续之前完成。第二个实例(存档),似乎是说,如果这个任务还没有完成,等到现在,直到它完成。如果我错了,请大家指正。

It seems that the await keyword is serving two different purposes. The first occurance (FetchAsync) seems to mean, "If this value is used later in the method and its task isn't finished, wait until it completes before continuing." The second instance (archive) seems to mean, "If this task is not yet finished, wait right now until it completes." If I'm wrong, please correct me.

这其实是完全不正确。这两个具有相同的含义。

This is actually completely incorrect. Both of these have the same meaning.

在你的第一种情况:

var document = await FetchAsync(urls[i]);

在这里会发生什么事,就是运行时说,开始打电话FetchAsync,那么当前执行点返回线程调用此方法。有没有等待在这里 - 相反,执行返回到调用同步上下文,事情不断翻腾。在未来的某个时刻,FetchAsync的任务将完成,而在这一点上,这code将继续在调用线程的同步上下文,并会出现下一个语句(分配文件变量)。

What happens here, is that the runtime says "Start calling FetchAsync, then return the current execution point to the thread calling this method." There is no "waiting" here - instead, execution returns to the calling synchronization context, and things keep churning. At some point in the future, FetchAsync's Task will complete, and at that point, this code will resume on the calling thread's synchronization context, and the next statement (assigning the document variable) will occur.

然后执行将继续,直到第二的await电话 - 此时,同样的事情会发生 - 如果任务&LT; T&GT; (归档)是不完整的,执行将被释放到调用上下文 - 否则,归档将设置

Execution will then continue until the second await call - at which time, the same thing will happen - if the Task<T> (archive) isn't complete, execution will be released to the calling context - otherwise, the archive will be set.

在第二种情况下,事情有很大的不同 - 在这里,你明确阻止,这意味着调用同步上下文将永远不会有机会执行任何code,直到你的整个方法完成。当然,仍然有不同步,而异步是code的此块完全包含 - 本贴code以外没有任何code将在此线程发生,直到所有的code完成。

In the second case, things are very different - here, you're explicitly blocking, which means that the calling synchronization context will never get a chance to execute any code until your entire method completes. Granted, there is still asynchrony, but the asynchrony is completely contained within this block of code - no code outside of this pasted code will happen on this thread until all of your code completes.

这篇关于如何C#5.0的异步等待功能从TPL有什么不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆