在指定的超时后未取消任务

时间:2016-07-21 03:01:26

标签: c# windows-runtime windows-store-apps task-parallel-library winrt-async

我使用StreamSocketListener等待端口上的连接。我不希望它永远听,它必须在特定的秒数后取消,我使用以下代码。

 remoteListener = new StreamSocketListener();
    try
    {
        CancellationTokenSource ctsTimeout = new CancellationTokenSource();
        ctsTimeout.CancelAfter(1000); // in milliseconds
        await remoteListener.BindServiceNameAsync(receivingPortForRemoteRequests.ToString()).AsTask(ctsTimeout.Token);
        remoteListener.ConnectionReceived += remoteListener_ConnectionReceived;
    }
    catch (Exception exc) // supposed to produce a TaskCanceledException
    {
        isCancelled = true;
    }

我的问题是这段代码在任何时间间隔之后都不会抛出Exception,而只是继续倾听。该代码基于我从this MSDN page找到的内容。

有谁知道我做错了什么?提前谢谢!

1 个答案:

答案 0 :(得分:2)

我想说你犯的主要错误是你将取消令牌传递给绑定套接字的任务,而不是任何实际监听的操作 。绑定操作只是将一个端口分配给套接字,并且通常在最坏的情况下在几毫秒内完成,在典型情况下很可能更快。在整整一秒钟之后,这种操作仍然无法进行。

如果没有明确说明您问题的好Minimal, Complete, and Verifiable example,则无法提供全面的答案。但是,有些建议:

  1. 首先,不要使用取消令牌。这不是你应该如何阻止套接听。相反,只需在必要时间后关闭套接字即可。您可以为此目的使用计时器,或首先调用async然后关闭套接字的await Task.Delay(...)方法。
  2. 将来,如果您确实有使用取消令牌的情况,则应仅捕获TaskCanceledException从不使用catch (Exception)进行例行处理异常;唯一合适的地方是您打算简单地记录或以其他方式报告异常然后终止该过程的情况。否则,只捕获您期望的例外情况,并为此制定好的处理计划。
  3. 您应该在绑定套接字之前订阅ConnectionReceived事件。否则,有可能(非常小,被授予)在您的代码准备好通过事件通知之前进行连接尝试。
  4. 上面的第一点和第三点在MSDN文档中进行了解释,该文档对正确使用此类进行了有用的总结。来自the documentation for StreamSocketListener

      

    典型的操作顺序如下:
      •创建StreamSocketListener   •使用Control属性检索StreamSocketListenerControl对象并设置所需的套接字服务质量。
      •将ConnectionReceived事件分配给事件处理程序   •调用BindServiceNameAsync或BindEndpointAsync方法以绑定到本地TCP端口号或服务名称。对于蓝牙RFCOMM,本地服务名称参数是蓝牙服务ID   •收到连接时,使用StreamSocketListenerConnectionReceivedEventArgs对象检索创建了StreamSocket对象的Socket属性。
      •使用StreamSocket对象发送和接收数据   •调用Close方法以停止侦听和接受传入的网络连接,并释放与StreamSocketListener对象关联的所有非托管资源。收到连接时创建的任何StreamSocket对象都不受影响,可以根据需要继续使用。