当 Task.IsCancelled 设置为 true 时?
Posted
技术标签:
【中文标题】当 Task.IsCancelled 设置为 true 时?【英文标题】:when Task.IsCancelled is set as true? 【发布时间】:2017-06-28 17:50:07 【问题描述】:什么时候来Task.IsCanceled = true;
代码:
var cts = new CancellationTokenSource();
string result = "";
cts.CancelAfter(10000);
try
Task t = Task.Run(() =>
using (var stream = new WebClient().OpenRead("http://www.rediffmail.com"))
result = "success!";
cts.Token.ThrowIfCancellationRequested();
, cts.Token);
Stopwatch timer = new Stopwatch();
timer.Start();
while (timer.IsRunning)
if (timer.ElapsedMilliseconds <= 10000)
if (result != "")
timer.Stop();
Console.WriteLine(result);
else
timer.Stop();
//cts.Cancel();
//cts.Token.ThrowIfCancellationRequested();
catch (OperationCanceledException)
Console.WriteLine(t.IsCanceled); // still its appear in false.
我的要求是 - 任务在 10 秒内未完成,需要取消任务。
所以我正在设置计时器并观看给定的秒数。它未完成意味着取消任务并显示错误消息。
【问题讨论】:
请附上Minimal, Complete, and Verifiable example。您显示的内容不完整。 取消token还不够,需要查看method
取消作业的代码
你能显示等待任务 t 的代码吗?正确地说,如果方法运行时间超过 20 秒,您想取消整个操作,是吗?
我将在哪里共享代码。这里无法分享代码。显示时间过长
【参考方案1】:
您必须将令牌传递给您的方法。它应该检查令牌并尊重对CancellationTokenSource
的Cancel()
的调用。
或者你自己做:
Task t = Task.Factory.StartNew(() =>
myResult = method(); // Request processing in parallel
cts.Token.ThrowIfCancellationRequested(); // React on cancellation
, cts.Token);
一个完整的例子是这样的:
async Task Main()
var cts = new CancellationTokenSource();
var ct = cts.Token;
cts.CancelAfter(500);
Task t = null;
try
t = Task.Run(() => Thread.Sleep(1000); ct.ThrowIfCancellationRequested(); , ct);
await t;
Console.WriteLine(t.IsCanceled);
catch (OperationCanceledException)
Console.WriteLine(t.IsCanceled);
输出是一个OperationCanceledException
被抛出,结果是
是的
如果您删除 ct.ThrowIfCancellationRequested();
部分,它将显示
错误
编辑:
现在,您已经更新了问题,一些 cmets 对此进行了更新。首先,您将不再需要计时器,因为您使用的是CancelAfter
方法。其次,你需要await
你的任务。所以这就是这样的:
string result = "";
cts.CancelAfter(10000);
Task t = null;
try
t = Task.Run(() =>
using (var stream = new WebClient().OpenRead("http://www.rediffmail.com"))
cts.Token.ThrowIfCancellationRequested();
result = "success!";
, cts.Token);
await t;
catch (OperationCanceledException)
Console.WriteLine(t.IsCanceled);
这应该表明t.IsCanceled
是true
但当然只有当WebClient
的调用需要超过10 秒时。
【讨论】:
Task t = Task.Factory.StartNew(() => myResult = method(); // 请求并行处理 , cts.Token); // 一段时间后 cts.cancel cts.Token.ThrowIfCancellationRequested();有可能吗?这里 t.iscancelled 永远不会出现 true。 你能显示等待任务 t 的代码吗?正确地说,如果方法运行时间超过 20 秒,您想取消整个操作,是吗? 如何分享代码?这里出现了太长的字符。 编辑或添加到您的问题中,这是最好的方法。 它不工作。 Web 客户端需要 10 秒。但它仍然没有来进行捕获操作。获得结果后,由于等待操作,只会返回结果。没有等待它可能吗?【参考方案2】:来自文档:
在以下任一条件下,任务将在 TaskStatus.Canceled 状态下完成:
它的 CancellationToken 在任务开始执行之前被标记为取消。
任务通过抛出带有相同 CancellationToken 的 OperationCanceledException 来确认其已发出信号的 CancellationToken 的取消请求。
任务通过调用 CancellationToken 上的 ThrowIfCancellationRequested 方法,在其已发出信号的 CancellationToken 上确认取消请求。
所以基本上你需要在你的任务中抛出一个OperationCanceledException
来强制状态,例如在你取消它之后执行cts.Token.ThrowIfCancellationRequested()
。
但是这种机制的意图有点相反。您取消源说,当用户按下表单上的取消按钮(从您的任务之外)时,任务只是验证是否在某些安全的情况下请求取消以取消其代码的点。
【讨论】:
以上是关于当 Task.IsCancelled 设置为 true 时?的主要内容,如果未能解决你的问题,请参考以下文章