如果使用本地方法,为什么comcellationToken不起作用?
鉴于以下代码,您希望在两种情况下都执行Dowait方法一秒钟。但是,它适用于第一种情况,但悬挂在第二个情况下。
如果我们在本地方法中添加异步/等待行为是预期的。
鉴于CT是结构,因此是按价值传递的,而不是参考,有人可以解释发生了什么吗?
using System.Diagnostics;
namespace ConsoleApp2
{
internal class Program
{
static async Task Main(string[] args)
{
//not using local method
using var cts1 = new CancellationTokenSource(TimeSpan.FromSeconds(1));
Console.WriteLine(await DoWait(cts1.Token));
//using a local method
Task<long> LocalMethod()
{
using var cts1 = new CancellationTokenSource(TimeSpan.FromSeconds(1));
return DoWait(cts1.Token);
}
Console.WriteLine(await LocalMethod());
}
static async Task<long> DoWait(CancellationToken ct)
{
var stopwatch = Stopwatch.StartNew();
var elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
try
{
while (true)
{
elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
ct.ThrowIfCancellationRequested();
await Task.Delay(10);
}
}
catch (OperationCanceledException) { }
return elapsedMilliseconds;
}
}
}
Given the following code you would expect that the DoWait method is executed for one second in both cases. However, it works for the first case but hangs for the second.
If we add async/await to the local method the behavior is as expected.
Given that that CTs are structs and hence passed around by value, not reference, can anyone explain explain what's going on?
using System.Diagnostics;
namespace ConsoleApp2
{
internal class Program
{
static async Task Main(string[] args)
{
//not using local method
using var cts1 = new CancellationTokenSource(TimeSpan.FromSeconds(1));
Console.WriteLine(await DoWait(cts1.Token));
//using a local method
Task<long> LocalMethod()
{
using var cts1 = new CancellationTokenSource(TimeSpan.FromSeconds(1));
return DoWait(cts1.Token);
}
Console.WriteLine(await LocalMethod());
}
static async Task<long> DoWait(CancellationToken ct)
{
var stopwatch = Stopwatch.StartNew();
var elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
try
{
while (true)
{
elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
ct.ThrowIfCancellationRequested();
await Task.Delay(10);
}
}
catch (OperationCanceledException) { }
return elapsedMilliseconds;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
concellationTokenSource
您在localmehtod
中创建该方法时正在处置该方法。由于被处置了,因此无法再取消您已经传递给dowait
的令牌。在您制作本地方法异步/等待的版本中,它不会被处置,因此可以按预期进行工作。
The
CancellationTokenSource
you're creating withinLocalMehtod
is being disposed when that method returns. Since it's disposed, it can no longer cancel the token you already passed toDoWait
.In the version where you make the local method async/await, it doesn't get disposed, so can carry on working as expected.