异步套接字读取:启动线程必须不被退出-该怎么做

本文关键字:退出 读取 套接字 启动 线程 异步 | 更新日期: 2023-09-27 18:06:56

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

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

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

我相信我碰到了一个记录在socket中的需求。EndReceive: http://msdn.microsoft.com/en-us/library/w7wtt64b.aspx。州:

一个给定线程发起的所有I/O将在该线程运行时被取消退出。如果线程退出,挂起的异步操作可能会失败

由于async方法在默认调度程序上运行,因此不能保证此要求。

有办法解决这个问题吗?我需要启动一个专用线程来启动I/O吗?

敬上,Dirk

异步套接字读取:启动线程必须不被退出-该怎么做

我在并行扩展论坛上问过同样的问题:

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

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

我建议使用永远不会终止的专用I/O线程。这就是很多真实世界的代码所做的。

最好的方法之一是让线程围绕GetQueuedCompletionStatus循环。如果你需要让一个I/O线程执行一个I/O操作,调用PostQueuedCompletionStatusQueueUserAPC来让I/O线程发布这个操作。

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

你可以使用书中最古老的技巧。让你的线程在一个永不结束的循环中休眠

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

注意,上面的代码是我用脑子写的。没有在Visual Studio中检查,因为我目前在Mac上工作。

当你需要的时候,你也需要写一些东西来退出线程,但这取决于你的应用程序是如何运行的。