操作超时TPL

时间:2013-07-19 16:59:08

标签: .net task-parallel-library

我需要监视任务并在需要的时间超过定义的超时时终止它。

到目前为止,我有许多尝试,从创建线程和发出线程中止等开始。然后,我决定使用TPL。

您必须假设WorkItem是一个黑盒子。您无权访问其源代码。因此,重写它以使其跟踪令牌是不现实的。这需要从外面进行控制。

有什么想法吗?

  public class WorkItem : IDisposable
  {
    private System.Diagnostics.Stopwatch _watch = new System.Diagnostics.Stopwatch();
    private List<string> _messages = new List<string>();

    public void WriteMessage(string message)
    {
      _messages.Add(message);
    }

    public void Run()
    {
      for (int i = 1; i <= 25; i++)
      {
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine("Slept one second after {0} iteration.", i);
      }
    }

    public void Dispose()
    {
      _watch.Stop();
      Console.WriteLine("Disposed... lived for {0} milliseconds", _watch.ElapsedMilliseconds);
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      int timeout = 5000;
      WorkItem item = new WorkItem();
      System.Threading.Tasks.Task task = System.Threading.Tasks.Task.Factory.StartNew<WorkItem>((arg) =>
      {
        WorkItem currentWorkItem = arg as WorkItem;
        currentWorkItem.Run();
        return currentWorkItem;
      }, item);

      bool wait = task.Wait(timeout);
      if (wait == false)
      {
        Console.WriteLine("It took more than {0} ms.", timeout);
        // Need a way to kill the task.
      }

      Console.WriteLine("Okay Waiting");
      Console.ReadKey();
    }
  }

1 个答案:

答案 0 :(得分:3)

Task没有办法让你在外部取消它。当你有一个黑匣子在运行时,没有人知道当你杀死它时可能会做什么。它可能是持有锁。它可能正在修改一些共享状态。它可以做任何数量的事情,如果被打断,将使你的程序处于未知且非常可能的腐败状态。中止线程就像关闭计算机的电源开关一样。没有人知道你可能会毁掉什么。

我非常强烈建议反对我要建议的内容,但如果你真的绝对必须在死亡的痛苦或失去工作的情况下拍摄自己的头脑...错误,给你的程序能够杀死你的黑匣子,然后用一个线程来做。

WorkItem threadResult = null;
Thread t = new Thread((arg) =>
    WorkItem currentWorkItem = arg as WorkItem;
    currentWorkItem.Run();
    threadResult = currentWorkItem;
  }, item);

// wait for thread to exit
bool done = t.Join(timeout);            
if (!done)
{
    t.Abort();
}

我再次否认您因使用此技术而可能遇到的任何负面后果。中止线程几乎总会让你遇到麻烦。