异步套接字读取:不能退出启动线程 - 该怎么办?

时间:2011-08-30 11:01:26

标签: c# multithreading asynchronous threadpool task-parallel-library

我有一个我异步读取的NetworkStream(使用async / await)

await Task<int>.Factory.FromAsync((cb, state) => stream.BeginRead(buffer, offset, readLen - offset), stream.EndRead, null);

不幸的是,有时会发生io异常:“由于线程退出或应用程序请求,I / O操作已中止。”

我相信我达到了Socke.EndReceive中记录的要求:http://msdn.microsoft.com/en-us/library/w7wtt64b.aspx。哪个州:

  

当该线程取消给定线程发起的所有I / O.   退出。如果线程退出,挂起的异步操作可能会失败   在操作完成之前。

由于异步方法在默认调度程序上运行,因此无法保证此要求。

有解决方法吗?我是否需要启动专用线程来启动I / O?

最好的问候,Dirk

3 个答案:

答案 0 :(得分:3)

我在parallelextensions论坛上提出了同样的问题:

http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/d116f7b0-c8ee-4ce4-a9b8-4c38120e45a4

基本上,ThreadPool不会停止任何具有异步I / O挂起的线程。因此,只要在ThreadPool上启动套接字操作,就不会发生此问题。

答案 1 :(得分:1)

我建议使用永不终止的专用I / O线程。这就是许多现实代码所做的事情。

执行此操作的最佳方法之一是让线程循环GetQueuedCompletionStatus。如果您需要让其中一个I / O线程执行I / O操作,请调用PostQueuedCompletionStatusQueueUserAPC以获取I / O线程以发布操作。

注意:您必须处理这些操作失败的情况。例如,QueueUserAPC如果太多的APC已经排队,则可能会失败。

答案 2 :(得分:-1)

您可以使用书中最古老的技巧。让你的线程在一个永无止境的循环中睡眠

while(true) {
    Threading.Sleep(TimeSpan.FromSeconds(1); 
}

请注意,我已经从头脑中编写了上述代码。因为我目前在Mac上工作,所以没有在Visual Studio中检查它。

此外,您还需要编写一些内容以便在需要时退出线程,但这取决于应用程序的流程。