23

我正在尝试熟悉 c# 的新 await/async 关键字,但我发现了几个我不太了解的方面。

  1. 让我们从竞争条件开始:

    Stream s=...
    ...
    for(int i=0;i<100;i++)
    {
        s.WriteAsync(new byte[]{i},0,1);
    }
    

    这会一直按预期工作吗(例如写入文件 12345 ..... 而不是 13254 或其他东西)?

    第二件事是,如果 async 函数不包含 await 运算符,则它会同步执行。而且,根据微软文档,异步函数总是在调用者线程中执行(与 BeginInvoke 相比)。这让我想到了接下来的 3 个问题:

  2. 在发布给调用者函数之前,执行了多少异步函数?

    async void MyAsyncFunction()
    {
        Operation1();
        Operation2();
        Operation3();
        ....
        Stream s=...;
        await s.WriteAsync(....);
    }
    

    在我读过的关于 await/async 的文章中,据说没有 await 运算符的 async 函数是按顺序执行的,而带有 async/await 的函数将立即返回。但它一直困扰着我,它MyAsyncFunction可能总是在执行 Operation1...Operation3 之前在它击中时释放await s.WriteAsync

  3. 如果我Thread.Sleep在这样的异步函数中使用怎么办:

    async void DoStuff()
    {
        Stream s=...;
        ...
        await s.WriteAsync(....);
        Thread.Sleep(10000);
        ....
    }
    

    Thread.Sleep 会阻塞执行它的整个线程还是仅仅阻塞异步函数?

  4. 如果我semaphore.Wait()在其中一个异步函数中使用,它会期望信号量被另一个异步函数释放。这会像线程一样运行,还是会导致死锁?

  5. await在异步函数之外不起作用。为什么?

4

3 回答 3

16

我建议你阅读我的async介绍

这会一直按预期工作吗(例如写入文件 12345 ..... 而不是 13254 或其他东西)?

不,您需要await调用WriteAsync.

在发布给调用者函数之前,执行了多少异步函数?

直到它await是一个尚未完成的操作。

Thread.Sleep 会阻塞执行它的整个线程还是仅仅阻塞异步函数?

Thread.Sleep- 和所有其他阻塞方法 - 将阻塞async方法和正在执行它的线程。

作为一般规则,不要在方法中使用任何阻塞方法async

如果我在其中一个异步函数中使用 semaphore.Wait() 会怎样,它会期望信号量被另一个异步函数释放。这会像线程一样运行,还是会导致死锁?

这完全取决于您的上下文。Wait是一个阻塞方法,所以如果“其他”async方法需要被阻塞方法持有的上下文,那么你就会死锁。

注意SemaphoreSlimasync- 友好的;您可以使用WaitAsync而不是Wait.

await 在异步函数之外不起作用。为什么?

因为async关键字启用await关键字。这样做是为了尽量减少新关键字对 C# 语言的影响和代码的可读性。

于 2012-11-17T14:03:54.863 回答
15

您可以在Eric Lippertawait的以下帖子中找到有关 operator 的问题的答案,他说:

“await”操作符……并不意味着“这个方法现在阻塞当前线程,直到异步操作返回”。那将使异步操作回到同步操作,这正是我们试图避免的。相反,它的意思与此相反;它的意思是“如果我们正在等待的任务还没有完成,那么注册这个方法的其余部分作为该任务的延续,然后立即返回给你的调用者;任务完成后将调用延续。——埃里克·利珀特

于 2012-11-17T10:38:40.117 回答
0

简而言之,答案似乎是“非常”。虽然以下内容可能无法回答您的所有问题,但我认为它适用于足够普遍的用例。想想你的 Stream 而不是他们所指的网络 IO。

在网络 IO 重叠的情况下,将使用 IO 完成端口,回调由硬件中断触发。

这意味着当我们“等待”完成时,不会消耗线程。[...]

可以在 1 个线程上完成所有操作。[...] 但是,它将取决于平台、“等待者”实现和正在使用的同步上下文。

http://social.msdn.microsoft.com/Forums/en-US/async/thread/a46c8a54-f8d4-4fa9-8746-64d6a3a7540d/

于 2012-11-17T09:36:13.280 回答