问题描述
我试图了解使用CancellationTokens并收听它们。我发现了一些示例,这些示例显示了如何注册侦听器,但是即使未取消该进程,它仍然会触发。
我的通话测试方法:
private static void TestRun2()
{
var cts = new CancellationTokenSource();
try
{
var options = new ParallelOptions
{
CancellationToken = cts.Token,};
Parallel.Invoke(options,() => TestMethod(cts.Token));
cts.Cancel();
cts.Dispose();
}
catch (OperationCanceledException ex)
{
cts.Cancel();
cts.Dispose();
Console.WriteLine("Timeout");
}
}
注册了CancellationToken的相关方法:
private static void TestMethod(CancellationToken token)
{
var wc = new WebClient();
wc.DownloadStringCompleted += (s,e) => Console.WriteLine("GetWebData: Request completed.");
// Cancellation on the token will
// call CancelAsync on the WebClient.
token.Register(() =>
{
wc.CancelAsync();
Console.WriteLine("GetWebData: Request cancelled!");
});
Console.WriteLine("GetWebData: Starting request.");
wc.DownloadStringAsync(new Uri("http://www.microsoft.com"));
}
当我强制取消时,它似乎可以工作...但是,当我不这样做时,仍然会调用该委托,并且我会在控制台上收到有关取消请求的通知。我环顾四周,却看不到为什么会不断发生这种情况的任何解释。
所以问题是为什么为什么在未取消请求时显示请求已取消?
解决方法
让我们看看这个:
Parallel.Invoke(options,() => TestMethod(cts.Token));
cts.Cancel();
cts.Dispose();
您开除TestMethod
。 TestMethod是异步的。它将立即返回。然后紧接着,您致电cts.Cancel()
发出取消信号。
它正在按设计工作。将您的回调更改为此:
wc.DownloadStringCompleted += (s,e) =>
Console.WriteLine($"GetWebData: Request completed. Cancelled: {e.Cancelled}");
它将输出:
GetWebData: Request completed. Cancelled: True
为了更好地说明我的观点,请尝试执行以下操作:
Parallel.Invoke(options,() => TestMethod(cts.Token));
Thread.Sleep(5000);
cts.Cancel();
cts.Dispose();
很明显,您不应该在最终实现中执行此操作,而只是出于演示目的。