什么时候用子任务处理 System.Threading.Task? [英] When to dispose of System.Threading.Task with child tasks?

查看:28
本文介绍了什么时候用子任务处理 System.Threading.Task?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个启动多个子任务的任务.(例如,任务 A 创建 B、C、D、E、F).我还创建了一个 System.Threading.Timer 来每 10 秒轮询一次数据库,以检查计划的项目是否被请求取消.如果是,它会设置 CancellationTokenSource 以便任务知道要取消.每个子任务,在本例中为 B、C、D、E、F,将在适当的时候取消(它们循环遍历文件并四处移动).

I have a task that launches several child tasks. (e.g., Task A creates B,C,D,E,F). I also create a System.Threading.Timer to poll a database every 10 seconds to check if the scheduled item was cancelled by request. If it does, it sets CancellationTokenSource so that the task knows to cancel. Each sub-task, in this case B,C,D,E,F, will cancel when appropriate (they are looping thru files and moving them around).

由于Task实现了IDisposable,我想知道从中再次调用Task.WaitAll是否是个好主意catch 块,等待取消传播.虽然取消请求将被处理,但子任务可能处于循环中间,并且在循环完成之前无法取消

Since Task implements IDisposable, I want to know if it is a good idea to call Task.WaitAll again from the catch block, to wait for the cancellations to propogate. While the cancellation request will be processed, the sub-tasks may be in the middle of a loop and can't cancel until that completes

但是,根据 MSDN:

However, per MSDN:

在释放对任务的最后一次引用之前,始终调用 Dispose.否则,在垃圾收集器调用 Task 对象的 Finalize 方法之前,它使用的资源不会被释放.

Always call Dispose before you release your last reference to the Task. Otherwise, the resources it is using will not be freed until the garbage collector calls the Task object's Finalize method.

我是否应该在我的任务数组上再次调用 wait 以便在数组中的每个任务上正确调用 Dispose()?

Should I call wait again on my task array in order to properly call Dispose() on each task in the array?

public class MyCancelObject
{
  CancellationTokenSource Source { get;set;}
  int DatabaseId { get;set;}   
}

private void CheckTaskCancelled(object state)
{
  MyCancelObject sourceToken = (MyCancelObject)state;

  if (!sourceToken.CancelToken.IsCancellationRequested)
  {
    //Check database to see if cancelled -- if so, set to cancelled
    sourceToken.CancelToken.Cancel();
  }
}

private void SomeFunc()
{
  Task.StartNew( () =>
  {
    MyCancelObject myCancelObject = new MyCancelObject(
      databaseId,
      new CancellationTokenSource());
    System.Threading.Timer cancelTimer = new Timer(
      new TimerCallback(CheckIfTaskCancelled),
      myCancelObject,
      10000,
      10000);        
    Task[] someTasks = new Task[someNumberOfTasks];

    for (int i = 0; i < someNumberOfTasks; i++)
      someTasks[i] = Task.Factory.StartNew(
        () =>
        {
          DoSomeWork(someObject, myCancelObject.CancelToken.Token);
        },
        TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning,
        myCancelObject.CancelToken.Token);

    try
    {
      Task.WaitAll(someTasks, cts);
    }
    catch (AggregateException)
    {
      //Do stuff to handle
    }
    catch (OperationCanceledException)
    {
      //Should I call Task.WaitAll(someTasks) again??
      //I want to be able to dispose.
    }
  }
}

推荐答案

我觉得我已经想通了,但我们非常欢迎任何想要添加其他有用内容的人.

I feel like I have figured this out, but anyone that would like to add anything else useful is more than welcome.

我只是从 catch 块中再次调用 Task.WaitAll() 以等待其他任务完成.全部完成后,我有一个 finally 块来清理数组中的所有任务.

I simply called Task.WaitAll() again from the catch block to wait for the other tasks to finish. After they have all finished, I have a finally block cleaning up all tasks in the array.

try
{
Task.WaitAll(someTaskArray, cancelToken)
}
catch (OperationCanceledException)
{
Task.WaitAll(someTaskArray);
}
finally
{
for (int i = 0; i < someTaskArray.Length; i++)
someTaskArray[i].Dispose();
}

这篇关于什么时候用子任务处理 System.Threading.Task?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆