超时并停止任务

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);

Here's the docs

超时后,您将设置 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; 
  }
}