我正在尝试熟悉c#的新await / async关键字,我发现了几个我无法理解的方面 .
- 让我们从竞争条件开始:
Stream s=...
...
for(int i=0;i<100;i++)
{
s.WriteAsync(new byte[]{i},0,1);
}
这将按预期工作(例如写入文件12345 .....而不是13254或其他东西)?
第二件事是异步函数如果不包含await运算符则同步执行 . 而且,根据microsoft文档,异步函数总是在调用者线程中执行(与BeginInvoke相比) . 这带来了3个下一个问题:
- 异步函数在释放给调用函数之前执行了多少?
async void MyAsyncFunction()
{
Operation1();
Operation2();
Operation3();
....
Stream s=...;
await s.WriteAsync(....);
}
在关于await / async的文章中,我说've read, it' s表示没有等待操作符的异步函数按顺序执行,并且async / await立即返回 . 但它唠叨我 MyAsyncFunction
可能总是在释放之前执行Operation1 ... Operation3,因为它命中 await s.WriteAsync
.
- 如果我在异步函数中使用
Thread.Sleep
,如下所示:
async void DoStuff()
{
Stream s=...;
...
await s.WriteAsync(....);
Thread.Sleep(10000);
....
}
Thread.Sleep会阻塞执行它的整个线程还是只阻止异步函数?
-
如果我在其中一个异步函数中使用
semaphore.Wait()
,它会期望其他异步函数释放信号量,该怎么办?这会像线程一样运行,还是会导致死锁? -
await
在异步函数之外不起作用 . 为什么?
3 回答
我建议你阅读我的async intro .
不 . 你需要
await
来调用WriteAsync
.直到
await
s尚未完成的操作 .Thread.Sleep
- 以及所有其他阻塞方法 - 将阻止async
方法和正在执行它的线程 .作为一般规则,请勿在
async
方法中使用任何阻止方法 .这完全取决于你的背景 .
Wait
是一种阻塞方法,因此如果"other"async
方法需要被阻塞方法保存的上下文,那么您将死锁 .请注意
SemaphoreSlim
是async
-friendly;你可以使用WaitAsync
而不是Wait
.因为
async
关键字启用await
关键字 . 这样做是为了最大限度地减少新关键字对C#语言和代码可读性的影响 .您可以在以下post by Eric Lippert中找到有关
await
运算符的问题的答案,其中他说:简而言之,似乎答案是“非常” . 虽然以下内容可能无法回答您的所有问题,但我认为它适用于一般情况下的用例 . 想想您的Stream而不是他们所指的网络IO .
http://social.msdn.microsoft.com/Forums/en-US/async/thread/a46c8a54-f8d4-4fa9-8746-64d6a3a7540d/