为什么在未取消令牌时注册委托会触发?
Why does registered delegate fire when token not canceled?
我正在尝试了解如何使用 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 是异步的。它将 return 立即 。然后紧接着,您通过调用 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();
显然,您不应该在最终实现中这样做,它只是为了演示目的。
我正在尝试了解如何使用 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 是异步的。它将 return 立即 。然后紧接着,您通过调用 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();
显然,您不应该在最终实现中这样做,它只是为了演示目的。