[英]How to stop async Task after a certain period of time
我试图在一段时间后停止 C# 中的任务。
对于我的代码: Task.Delay().Wait() 应该只代表 Task 所做的一些工作。
我的代码:
public static void Main()
{
Console.WriteLine("starting app");
try
{
Console.WriteLine("before");
DoStuff(1000);
Console.WriteLine("after");
}
catch
{
Console.WriteLine("TIMEOUT");
}
Console.WriteLine("Main finished wait 5 sec now");
Task.Delay(10000).Wait();
Console.WriteLine("Closing app now");
}
public static async Task DoStuff(int time)
{
Task real = Task.Run(()=>
{
Task.Delay(2000).Wait();
Console.WriteLine("Task Running");
Task.Delay(2000).Wait();
Console.WriteLine("still running");
Task.Delay(2000).Wait();
Console.WriteLine("Not dead yet");
Task.Delay(1000).Wait();
Console.WriteLine("Task done");
Task.Delay(5000);
});
bool success = real.Wait(time);
if ( success )
{
Console.WriteLine("Task finished in time");
await real;
}
else
{
Console.WriteLine("Task did not finish");
real.Dispose();
throw new TimeoutException("The task took too long");
}
}
我已经尝试使用取消令牌,但我没有循环来检查每次迭代的令牌。 所以我尝试用Task.Wait(time)
,我得到了正确的消息,但是在使用Task.Dispose()
方法后任务并没有停止。 我得到以下 output:
所以我得到了当前的 output 但任务继续在后面运行..关于如何解决这个问题的任何想法?
首先:永远不要Wait()
任务(除非你知道他们已经完成); 使用await
。 至于超时:可以让CancellationTokenSource
延迟后超时,如下。
请注意,取消令牌不会中断代码 - 您(或其他代码,如Task.Delay
的情况)需要检查取消(例如ThrowIfCancellationRequested()
),或者您需要使用Register(...)
添加一个回调,当它被取消时将被调用。
using System;
using System.Threading;
using System.Threading.Tasks;
static class P
{
public static async Task Main()
{
Console.WriteLine("starting app");
try
{
Console.WriteLine("before");
await DoStuffAsync(1000);
Console.WriteLine("after");
}
catch
{
Console.WriteLine("TIMEOUT");
}
Console.WriteLine("Main finished wait 5 sec now");
await Task.Delay(5000);
Console.WriteLine("Closing app now");
}
public static async Task DoStuffAsync(int time)
{
using var cts = new CancellationTokenSource(time); // assuming here that "time" is milliseconds
Task real = Task.Run(async () =>
{
await Task.Delay(2000, cts.Token);
Console.WriteLine("Task Running");
await Task.Delay(2000, cts.Token);
Console.WriteLine("still running");
await Task.Delay(2000, cts.Token);
Console.WriteLine("Not dead yet");
await Task.Delay(2000, cts.Token);
Console.WriteLine("Task done");
await Task.Delay(2000, cts.Token);
});
bool success;
try
{
await real;
success = true;
}
catch (OperationCanceledException)
{
success = false;
}
if (success)
{
Console.WriteLine("Task finished in time");
}
else
{
Console.WriteLine("Task tool too long");
}
}
}
请注意,您也可以将取消令牌传递给Task.Run
,但这只是在执行回调之前进行检查 - 而且通常不会有明显的延迟,所以......通常不值得。
附加说明:如果您想确定取消的确切内容(即OperationCanceledException
来自cts
):
catch (OperationCanceledException cancel) when (cancel.CancellationToken == cts.Token)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.