- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
取消下面的正确方法是什么?
var tcpListener = new TcpListener(connection);
tcpListener.Start();
var client = await tcpListener.AcceptTcpClientAsync();
简单地调用 tcpListener.Stop()
似乎会导致 ObjectDisposedException
而 AcceptTcpClientAsync
方法不接受 CancellationToken
结构。
我是否完全遗漏了一些明显的东西?
最佳答案
假设您不想调用 Stop
method在 TcpListener
class 上,这里没有完美的解决方案。
如果您不介意在特定时间范围内操作未完成时收到通知,但允许原始操作完成,那么您可以创建一个扩展方法,如下所示:
public static async Task<T> WithWaitCancellation<T>(
this Task<T> task, CancellationToken cancellationToken)
{
// The tasck completion source.
var tcs = new TaskCompletionSource<bool>();
// Register with the cancellation token.
using(cancellationToken.Register( s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs) )
{
// If the task waited on is the cancellation token...
if (task != await Task.WhenAny(task, tcs.Task))
throw new OperationCanceledException(cancellationToken);
}
// Wait for one or the other to complete.
return await task;
}
以上来自Stephen Toub's blog post "How do I cancel non-cancelable async operations?" .
这里需要重复的警告,这实际上并没有取消操作,因为没有重载AcceptTcpClientAsync
method。这需要 CancellationToken
,它无法被取消。
这意味着如果扩展方法指示取消确实发生了,那么您正在取消对原始Task
回调的等待。 ,不取消操作本身。
为此,这就是为什么我将方法从 WithCancellation
重命名为 WithWaitCancellation
以指示您正在取消等待,不是实际操作。
从那里开始,它很容易在您的代码中使用:
// Create the listener.
var tcpListener = new TcpListener(connection);
// Start.
tcpListener.Start();
// The CancellationToken.
var cancellationToken = ...;
// Have to wait on an OperationCanceledException
// to see if it was cancelled.
try
{
// Wait for the client, with the ability to cancel
// the *wait*.
var client = await tcpListener.AcceptTcpClientAsync().
WithWaitCancellation(cancellationToken);
}
catch (AggregateException ae)
{
// Async exceptions are wrapped in
// an AggregateException, so you have to
// look here as well.
}
catch (OperationCancelledException oce)
{
// The operation was cancelled, branch
// code here.
}
请注意,您必须为您的客户端包装调用以捕获 OperationCanceledException
如果等待被取消,则抛出实例。
我还投入了一个 AggregateException
catch,因为当从异步操作抛出异常时,异常会被包装(在这种情况下,您应该自己测试)。
这就留下了一个问题,面对像 Stop
method 这样的方法,哪种方法更好。 (基本上,无论发生什么,都会猛烈地破坏一切),当然,这取决于您的情况。
如果您不共享您正在等待的资源(在本例中为 TcpListener
),那么调用 abort 方法并吞下任何资源可能会更好来自您正在等待的操作的异常(当您调用停止并在您正在等待操作的其他区域监视该位时,您必须稍微翻转)。这给代码增加了一些复杂性,但如果您关心资源利用率和尽快清理,并且您可以选择,那么这就是方法。
如果资源利用率不是问题,并且您愿意使用更合作的机制,并且您不共享资源,那么使用 WithWaitCancellation
方法很好。这里的优点是它的代码更清晰,更易于维护。
关于c# - 取消不接受 CancellationToken 的异步操作的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40504418/
原因是如果它是CancellationToken.None,我需要添加一个超时(所以一个新的CancellationToken 来自CancellationTokenSource),例如 if (ca
我认为 RunAsync 方法采用 CancellationToken 作为参数,这很棒。 不幸的是,根据我的观察,我从未被取消。 当然,取消RunAsync 方法并调用OnCloseAsync 会有
我正在尝试使用取消标记从另一个线程中跳出循环: using System; using System.Threading; using System.Threading.Tasks; namespac
我对 AzureFunctions 还很陌生,所以请原谅我问一个简单的问题...... 我有以下代码,当队列中有一个项目时会触发该代码 [FunctionName("ProcessCompanies"
我有以下异步函数: private async Task ValidateFtpAsync() { return await Task.Run( ()
.NET 中的 TPL 新手。尝试了解 CancellationToken 以及它们如何收到取消正在执行的任务的信号。下面的代码只传输一个被取消的任务,因为相同的 token 被传递给两个任务。我的假
我有一个计时器,每 2 秒启动 2 个任务...我在一个简单的列表中跟踪这些任务(这样我就可以在停止应用程序时等待它们完成)。 任务有效地转到数据库,运行几个更新并完成。 任务本身的运行时间不会超过一
在没有搭建快速测试台的情况下;我想我会很快问 SO 看看是否有人知道这个答案。 此外,它可能还有一个额外的好处,即通知可能遇到类似情况的其他用户。 假设我有一个长期存在的 CancellationTo
我的 Xamarin.Forms 项目出现以下错误: at System.Threading.CancellationToken.ThrowOperationCanceledException (
我对如何为以下情况实现取消 token 感到有些困惑。 假设我有一个方法,它有一个取消 token ,没有像这样指定超时。 public static async Task DoSomeAsyncTh
.NET 4.5.1:看来,我无法使用 CancellationTokenSource 内置超时取消在任务中运行的阻塞方法。 class Program { static void Main(
我想使用锁或类似的同步来保护临界区。同时我想听一个CancellationToken。 现在我正在使用这样的互斥锁,但互斥锁的性能不佳。我可以使用任何其他同步类(包括新的 .Net 4.0)来代替互斥
这是我的情况: private CancellationTokenSource cancellationTokenSource; private CancellationToken c
我有一个用于各种任务的 token ,我需要更好地管理它们的取消,以便收到我可以使用的取消通知: token.Register(RegisterMethod); 我怎样才能删除这个“订阅”?有什么办法
我启动一个任务,然后启动其他任务等等。给定那棵树,如果任何任务失败,则整个操作的结果都是无用的。我正在考虑使用取消 token 。令我惊讶的是, token 没有“CancelThisToken()”
我今天早上一直在研究 Async CTP,并且有一个带有 button 和 label 的简单程序。单击按钮,它开始更新标签,停止按钮,它停止写入标签。但是,我不确定如何重置 Cancellation
我有一些异步代码,我想将其添加到 CancellationToken 中。但是,有很多实现不需要这样做,所以我想要一个默认参数 - 也许是 CancellationToken.None。然而, Tas
这段代码执行时 cancellationToken.ThrowIfCancellationRequested(); try catch block 不处理异常。 public Enumerab
最近我遇到了a Microsoft interface使用一个非常不寻常的 API: public interface IHostApplicationLifetime { public Ca
CancellationToken.CanBeCanceled 上的文档描述了它的作用,但没有提到它什么时候可能是假的。因此,我不完全清楚何时应该注意此属性。 在什么情况下它可以是假的,我应该什么时候
我是一名优秀的程序员,十分优秀!