异步套接字读取:不能退出启动线程 – 该怎么办?
我有一个我异步读取的NetworkStream(使用async / await)
await Task.Factory.FromAsync((cb, state) => stream.BeginRead(buffer, offset, readLen - offset), stream.EndRead, null);
不幸的是,有时会发生ioexception:“由于线程退出或应用程序请求,I / O操作已中止。”
我相信我达到了Socke.EndReceive中记录的要求: http : //msdn.microsoft.com/en-us/library/w7wtt64b.aspx 。 哪个州:
当该线程退出时,由给定线程启动的所有I / O都将被取消。 如果线程在操作完成之前退出,则挂起的异步操作可能会失败。
由于异步方法在默认调度程序上运行,因此无法保证此要求。
有没有解决的办法? 我是否需要启动专用线程来启动I / O?
最好的问候,德克
我在parallelextensions论坛上提出了同样的问题:
基本上,ThreadPool不会停止任何具有异步I / O挂起的线程。 因此,只要在ThreadPool上启动套接字操作,就不会发生此问题。
我建议使用永不终止的专用I / O线程。 这就是很多现实代码所做的事情。
最好的方法之一是让线程循环GetQueuedCompletionStatus
。 如果需要使其中一个I / O线程执行I / O操作,请调用PostQueuedCompletionStatus
或QueueUserAPC
以获取I / O线程以发布操作。
小心 :您必须处理这些操作失败的情况。 例如,如果有太多的APC已经排队, QueueUserAPC
可能会失败。
你可以使用书中最古老的技巧。 让你的线程在一个永无止境的循环中睡眠
while(true) { Threading.Sleep(TimeSpan.FromSeconds(1); }
请注意,我刚刚从脑子里写了上面的代码。 因为我目前在Mac上工作,所以没有在Visual Studio中检查它。
此外,您还需要编写一些内容以便在需要时退出线程,但这取决于应用程序的流程。