2009-12-06 89 views
6

我使用asio同步套接字从后台线程通过TCP读取数据。这被封装在一个“服务器”类中。中断boost :: asio同步读取?

但是,我希望线程在调用此类的析构函数时退出。 问题是,对任何读取函数的调用都会阻塞,所以线程不能轻易终止。在Win32中有一个API:WaitForMultipleObjects这将做我想要的。

我该如何达到与提升类似的效果?

回答

2

在我们的应用程序中,我们设置“终止”条件,然后使用线程正在监听的端口的自连接,以便它醒来,记录终止条件并终止。

你也可以检查boost实现 - 如果他们只是在套接字上进行一个简单的读操作(即,不在内部使用像WaitForMultipleObjects这样的东西),那么你可能会得出结论:没有任何东西可以简单干净地解除阻塞线程。如果他们在等待多个对象(或一个完成端口),你可以四处挖掘,看看唤醒阻塞线程的能力是否暴露在外。

最后,你可以杀死这个线程 - 但是你必须走出提升之外才能做到这一点,并理解后果,比如悬挂或泄露的资源。如果你正在关闭,这可能不是一个问题,这取决于该线程正在做什么。

2

我发现没有简单的方法来做到这一点。据说,有办法取消win32 IOCP,但在Windows XP上无法正常工作。 MS确实为Windows Vista和Windows 7进行了修复。推荐的取消asio async_readasync_write的方法是关闭插槽。

  • [析]注意,我们要拆毁
  • [析]关闭套接字
  • [析]等待完成处理

  • [完成]如果拆了,我们只是失败因为套接字关闭,通知析构函数完成处理程序已完成。

  • [完成]立即返回。

如果您选择实现此目标,请小心。关闭套接字非常简单。 '等待完成处理程序'然而却是巨大的下界。当服务器的线程和析构函数进行交互时,可能会出现一些细微的角落情况和竞态条件。

这是不够,我们建立了一个完成的包装(类似于io_service::strand微妙只是为了处理同步取消所有未决的完成回调。

1

最好的方法是创建一个socketpair(),(不管它是什么在boost::asio的说法),加阅读器结束事件循环,然后关闭书写器端,您将立即在该插槽上发生eof事件唤醒。

线程必须自动关闭。

线程应在其析构函数,有以下的产卵:

~object() 
{ 
    shutdown_queue.shutdown(); // ask thread to shut down 
    thread.join();    // wait until it does 
} 
-1

使用socket.cancel();结束在套接字上阻塞的所有当前异步操作。客户端套接字可能需要在循环中被终止。我从来不需要关闭服务器,但是可以使用shared_from_this()并在循环中运行cancel()/ close(),这与增强聊天示例async_如何写入所有客户端类似。