6

我有一个的NetworkStream我读异步(使用异步/等待)异步套接字读取:不能退出启动线程 - 该怎么办?

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?

最好的问候,德克

+0

您确定适用于异步I/O吗?我们已经在Mindtouch DReAM上使用了多年网络流的Begin/End,并且它始终将启动线程释放回线程池。 –

+0

Hello Arne,这不同于释放非托管线程。据我了解,这种行为的意思是“帮助”:当线程终止时,与其关联的任何工作都将被取消。 这就是说,我有麻烦在我自己的机器上重现它。它发生在构建服务器上,在该服务器上运行数百个测试,每个启动/停止线程以及快速连续创建和卸载appdomains。我看到的SocketException是EndReceive上的SocketError.OperationAborted。 –

+0

看起来我误解了那个页面。这确实是不幸的行为,因为异步点不必担心启动线程。 –

回答

-1

您可以在手册中使用的最古老的伎俩。让你的线程睡在一个永无止境的循环中

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

请注意,我已经写了上面的代码只是从我的头上。由于我目前在我的Mac上工作,所以没有在Visual Studio中检查它。

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

+2

如果你打算块,为什么要使用async API? – CodesInChaos

1

我会推荐使用永不终止的专用I/O线程。这是很多现实世界的代码所做的。

这样做的最好方法之一是让线程绕着GetQueuedCompletionStatus循环。如果需要使其中一个I/O线程执行I/O操作,请调用PostQueuedCompletionStatusQueueUserAPC以使I/O线程发布操作。

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