首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >.NET取消异步I/O操作

.NET取消异步I/O操作
EN

Stack Overflow用户
提问于 2011-09-11 12:55:34
回答 3查看 2.2K关注 0票数 4

在这种情况下,我正在编写一个TCP/IP服务器,并且使用TcpListener.BeginAcceptTcpClient()来接受传入的连接。服务器逻辑是在一个实现IDisposable接口的类中实现的:当调用Dispose()时,我想取消BeginAcceptTcpClient()操作。

现在,更一般的术语是:当使用.NET的异步I/O模型(Begin*和End*)时,我如何取消这些操作?

我的想法是这样的:

代码语言:javascript
运行
复制
private volatile bool canceledFlag = false;

this.listener.BeginAcceptTcpClient(asyncResult =>
{
    if(this.canceledFlag) return;

    // ...
}, null);

also ()将标志设置为true,并调用this.listener.Stop()。然而,我记得我读过这样的文章:对于每一个开始*调用,必须有一个匹配的结束*调用,否则就会发生糟糕的事情。

那我该怎么做呢?请注意,我正在寻找一个通用解决方案,用于取消Begin*和End*方法--我刚刚给出了我的具体使用场景,以帮助您理解我的问题。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-11 13:34:20

一般的解决方案是对调用其BeginXxxx()方法的任何对象调用Close()或Dispose()。这将导致回调运行,当调用EndXxxx()时,您将得到一个ObjectDisposedException。你应该抓住它,并把它当作“结束使用”的信号,立即清理并退出回调。尽管对此不屑一顾,但使用异常来控制流量是不可避免的。

对于TcpListener,使用Server.Dispose()比调用Stop()更有效。

票数 7
EN

Stack Overflow用户

发布于 2011-09-11 13:46:33

我推荐的替代方案不是使用异步开始结束模式,而是使用任务。

您可以使用TaskFactory.FromAsync重载之一从开始/结束方法创建任务,并使用此方法。您可以使用此.ContinueWith重载指定使用自己的CancellationToken来停止它的延续。建议您尽可能地使用任务,因为下一个版本的C#将在任务的基础上构建它的异步/等待支持。

下面是一个很好的文章,它解释了常见的模式和任务

备注:

在我最初的回答中,我说您可以使用.Dispose来终止任务,但是这可能会导致严重的问题,因为您只能在已完成的状态下处理任务。

票数 1
EN

Stack Overflow用户

发布于 2011-09-11 14:06:55

异步进程完成时调用AsyncCallback。它允许异步线程重新加入原始线程,然后任何异常都会出现(而不是在后台丢失)。它还允许您捕获任何返回值。

通常,您将按照以下方式使用Begin / End模式:

代码语言:javascript
运行
复制
  Action action = () = > DoSomething();
  action.BeginInvoke(action.EndInvoke, null);

代码语言:javascript
运行
复制
 Action action = () = > DoSomething();
 action.BeginInvoke(OnComplete, null);

 private void OnComplete(IAsyncResult ar)
 {
     AsyncResult result = (AsyncResult)ar;
     var caller = (Action)result.AsyncDelegate;
     caller.EndInvoke();

     // do something else when completed
 }

具体的实现需要提供一种在完成之前取消异步进程的方法。通常,这是通过内部提前停止任务的CancelAsync实现完成的。在TcpListener的情况下,只需调用listener.Server.Dispose();

代码语言:javascript
运行
复制
 TcpListener listener = new TcpListener(port);
 IAsyncResult = listener.BeginAcceptTcpClient(listener.EndAcceptTcpClient, null);

 // on dispose
 listener.Server.Dispose();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7378320

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档