我正在使用C#中的async / await,虽然我认为我理解了大部分概念,但我无法解释为什么代码行" var rxres = await ..."第一次在我的UDP线程上运行,并且在工作线程上进一步接收数据包之后。据我了解,我不是"屈服"回到线程函数,它仍处于活动状态,所以ReceiveAsync的所有调用都应该在我创建的线程上运行。
static void Main(string[] args)
{
var ewh = new EventWaitHandle(false, EventResetMode.ManualReset);
var udpThread = new Thread(async () =>
{
ListenUdpAsync().Wait();
});
udpThread.Name = "UDP THREAD";
udpThread.Start();
ewh.WaitOne();
}
static public async Task ListenUdpAsync()
{
var localPort = 5555;
var localBind = new IPEndPoint(IPAddress.Any, localPort);
using (var udpc = new UdpClient(localBind))
{
while(true)
{
var rxres = await udpc.ReceiveAsync();
Console.WriteLine("Rx From: " + rxres.RemoteEndPoint);
Console.WriteLine("Rx Data: " + Encoding.ASCII.GetString(rxres.Buffer));
}
}
}
答案 0 :(得分:4)
我不是"屈服"回到线程函数
该方法产生一次命中await udpc.ReceiveAsync()
,这就是async-await的工作原理。 ListenAsync
本身同步阻塞,但由于没有同步上下文发挥作用,延续可以将自己编组到任意线程池线程上。
所以ReceiveAsync的所有调用都应该在我创建的线程上运行。
不是真的。通常,当您在控制台应用程序内运行时,它使用默认的TaskScheduler
,它在内部使用线程池在任意线程池线程上执行延续。一个ReceiveAsync()
完成,它的继续需要在某个地方安排,那个地方在线程池上。
在旁注中 - 没有理由在委托上使用async
修饰符,因为您不是在等待内部任何内容,而是同步阻止。