超时并停止任务
Timeout and stop a Task
我有一个控制台应用程序,
{
StartThread();
//must be true, windows system wants to know it is started
return true;
}
我正在尝试为此任务创建安全超时功能。但是任务保持 运行...
DoSomething 方法调用其他异步方法并等待它们的结果
有谁知道为什么我的任务不会停止?也许是一个很好的代码示例,说明该怎么做
public async void StartThread()
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
try
{
var timeout = 1000;
Task task = new Task(() => DoSomething(token), token);
task.Start();
if (await Task.WhenAny(task, Task.Delay(timeout, token)) == task)
{
if (token.IsCancellationRequested)
task.Dispose();
await task;
if (task.IsCompleted)
{
task.Dispose();
tokenSource.Cancel();
tokenSource.Dispose();
}
else
{
log.WriteToFile("Timeout_ ");
}
}
else
tokenSource.Cancel();
}
catch (Exception e)
{
Console.WriteLine("--StartThread ...there is an exception----");
}
finally
{
Thread.Sleep(300000); // 5 minutter
StartThread();
}
}
您几乎不应该 Dispose
一个 Task
,因为物联网由 C# 内部管理并得到妥善处理。还有,你Dispose
太急切了,例如:
if (token.IsCancellationRequested)
task.Dispose();
await task;
我不这么认为,如果任务 已取消 并且 已处理,您仍然希望等待任务。我想这根本行不通。
此外,如果您使用 async
,请不要混用诸如 Thread.Sleep
之类的阻塞调用 - 这可能会导致灾难...
毕竟,您使用带有一些延迟任务的取消令牌来模拟超时 - 这没关系,但是当您手头有很好的 API 时,为什么要放置不必要的代码。只需使用 CancellationTokenSource
:
的特殊构造函数
public CancellationTokenSource (int millisecondsDelay);
超时后,您将设置 CancellationToken
,然后立即让线程休眠 5 分钟。因此 DoSomething()
永远没有机会继续 运行 并对令牌被取消做出反应。
虽然没有从给定的 timeout
创建 CancellationTokenSource
?
var timeout = 1000;
//DONE: don't forget to dispose CancellationTokenSource instance
using (var tokenSource = new CancellationTokenSource(timeout)) {
try {
var token = tokenSource.Token;
//TODO: May be you'll want to add .ConfigureAwait(false);
Task task = Task.Run(() => DoSomething(token), token);
await task;
// Completed
}
catch (TaskCanceledException) {
// Cancelled due to timeout
log.WriteToFile("Timeout_ ");
}
catch (Exception e) {
// Failed to complete due to e exception
Console.WriteLine("--StartThread ...there is an exception----");
//DONE: let's be nice and don't swallow the exception
throw;
}
}
我有一个控制台应用程序,
{
StartThread();
//must be true, windows system wants to know it is started
return true;
}
我正在尝试为此任务创建安全超时功能。但是任务保持 运行...
DoSomething 方法调用其他异步方法并等待它们的结果
有谁知道为什么我的任务不会停止?也许是一个很好的代码示例,说明该怎么做
public async void StartThread()
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
try
{
var timeout = 1000;
Task task = new Task(() => DoSomething(token), token);
task.Start();
if (await Task.WhenAny(task, Task.Delay(timeout, token)) == task)
{
if (token.IsCancellationRequested)
task.Dispose();
await task;
if (task.IsCompleted)
{
task.Dispose();
tokenSource.Cancel();
tokenSource.Dispose();
}
else
{
log.WriteToFile("Timeout_ ");
}
}
else
tokenSource.Cancel();
}
catch (Exception e)
{
Console.WriteLine("--StartThread ...there is an exception----");
}
finally
{
Thread.Sleep(300000); // 5 minutter
StartThread();
}
}
您几乎不应该 Dispose
一个 Task
,因为物联网由 C# 内部管理并得到妥善处理。还有,你Dispose
太急切了,例如:
if (token.IsCancellationRequested)
task.Dispose();
await task;
我不这么认为,如果任务 已取消 并且 已处理,您仍然希望等待任务。我想这根本行不通。
此外,如果您使用 async
,请不要混用诸如 Thread.Sleep
之类的阻塞调用 - 这可能会导致灾难...
毕竟,您使用带有一些延迟任务的取消令牌来模拟超时 - 这没关系,但是当您手头有很好的 API 时,为什么要放置不必要的代码。只需使用 CancellationTokenSource
:
public CancellationTokenSource (int millisecondsDelay);
超时后,您将设置 CancellationToken
,然后立即让线程休眠 5 分钟。因此 DoSomething()
永远没有机会继续 运行 并对令牌被取消做出反应。
虽然没有从给定的 timeout
创建 CancellationTokenSource
?
var timeout = 1000;
//DONE: don't forget to dispose CancellationTokenSource instance
using (var tokenSource = new CancellationTokenSource(timeout)) {
try {
var token = tokenSource.Token;
//TODO: May be you'll want to add .ConfigureAwait(false);
Task task = Task.Run(() => DoSomething(token), token);
await task;
// Completed
}
catch (TaskCanceledException) {
// Cancelled due to timeout
log.WriteToFile("Timeout_ ");
}
catch (Exception e) {
// Failed to complete due to e exception
Console.WriteLine("--StartThread ...there is an exception----");
//DONE: let's be nice and don't swallow the exception
throw;
}
}