指定超时后任务未取消

Task not cancelled after a specified timeout

我正在使用 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.

中找到的内容

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

我想说你犯的主要错误是你将取消令牌传递给 绑定 套接字的任务,而不是实际上 [=25] 的任何操作=]听。绑定操作简单地为套接字分配一个端口,最坏的情况下通常会在几毫秒内完成,在典型情况下很可能更快。整整一秒后,此操作不可能仍在进行中。

如果没有很好的 Minimal, Complete, and Verifiable example 清楚地说明您的问题,就不可能提供彻底的答案。但是,一些建议:

  1. 首先,不要费心使用取消令牌。这不是你应该如何阻止套接字监听。相反,只需在必要的时间后关闭套接字。为此,您可以使用计时器,或者使用先调用 await Task.Delay(...) 然后关闭套接字的 async 方法。
  2. 将来,如果您确实有适合使用取消令牌的场景,您应该只捕获 TaskCanceledException从不使用catch (Exception)进行常规异常处理;唯一合适的地方是您打算简单地记录或报告异常然后终止进程的场景。否则,只捕获您期望的异常以及您有好的处理计划。
  3. 您应该在绑定套接字之前订阅ConnectionReceived事件。否则,有可能(非常小,当然)在您的代码准备好通过事件通知之前进行连接尝试。

上面的第一点和第三点在 MSDN 文档中得到了解决,该文档对如何正确使用此 class 进行了有用的总结。来自 the documentation for StreamSocketListener:

The typical order of operations is as follows:
• Create the StreamSocketListener.
• Use the Control property to retrieve a StreamSocketListenerControl object and set the socket quality of service required.
• Assign the ConnectionReceived event to an event handler.
• Call the BindServiceNameAsync or BindEndpointAsync method to bind to a local TCP port number or service name. For Bluetooth RFCOMM, the local service name parameter is the Bluetooth Service ID.
• When a connection is received, use the StreamSocketListenerConnectionReceivedEventArgs object to retrieve the Socket property with the StreamSocket object created.
• Use the StreamSocket object to send and receive data.
• Call the Close method to stop listening for and accepting incoming network connections and release all unmanaged resources associated with the StreamSocketListener object. Any StreamSocket objects created when a connection is received are unaffected and can continue to be used as needed.