Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 何时处置带有子任务的System.Threading.Task?_C#_Multithreading_Task - Fatal编程技术网

C# 何时处置带有子任务的System.Threading.Task?

C# 何时处置带有子任务的System.Threading.Task?,c#,multithreading,task,C#,Multithreading,Task,我有一个任务可以启动几个子任务。(例如,任务A创建B、C、D、e、F)。我还创建了一个System.Threading.Timer,每10秒轮询一个数据库,以检查计划项目是否被请求取消。如果是,则设置CancellationTokenSource,以便任务知道要取消。每个子任务(在本例中为B、C、D、E、F)将在适当的时候取消(它们在文件中循环并移动) 由于Task实现了IDisposable,我想知道从catch块再次调用Task.WaitAll是否是一个好主意,以等待取消的执行。当取消请求将

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

由于
Task
实现了
IDisposable
,我想知道从
catch
块再次调用
Task.WaitAll
是否是一个好主意,以等待取消的执行。当取消请求将被处理时,子任务可能处于一个循环的中间,并且直到完成

才能取消。 但是,根据MSDN:

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

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

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.
    }
  }
}
公共类MyCancelObject
{
CancellationTokenSource源{get;set;}
int DatabaseId{get;set;}
}
私有无效检查任务已取消(对象状态)
{
MyCancelObject sourceToken=(MyCancelObject)状态;
如果(!sourceToken.CancelToken.IsCancellationRequested)
{
//检查数据库以查看是否已取消--如果是,则设置为已取消
sourceToken.CancelToken.Cancel();
}
}
私有void SomeFunc()
{
Task.StartNew(()=>
{
MyCancelObject MyCancelObject=新的MyCancelObject(
数据库ID,
新的CancellationTokenSource());
System.Threading.Timer cancelTimer=新计时器(
新TimerCallback(检查是否已取消),
我的取消对象,
10000,
10000);        
Task[]someTasks=新任务[someNumberOfTasks];
for(int i=0;i
{
DoSomeWork(someObject,myCancelObject.CancelToken.Token);
},
TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning,
myCancelObject.CancelToken.Token);
尝试
{
Task.WaitAll(someTasks,cts);
}
捕获(聚合异常)
{
//做事
}
捕获(操作取消异常)
{
//我应该再次调用Task.WaitAll(someTasks)吗??
//我希望能够处理。
}
}
}

我觉得我已经弄明白了这一点,但是任何想添加其他有用内容的人都非常欢迎

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

try
{
Task.WaitAll(someTaskArray, cancelToken)
}
catch (OperationCanceledException)
{
Task.WaitAll(someTaskArray);
}
finally
{
for (int i = 0; i < someTaskArray.Length; i++)
someTaskArray[i].Dispose();
}
试试看
{
Task.WaitAll(someTaskArray,cancelToken)
}
捕获(操作取消异常)
{
Task.WaitAll(someTaskArray);
}
最后
{
for(int i=0;i
我测试了一些代码,发现可以再次调用
任务。WaitAll
可以安全地等待可能仍在运行的任务。之后,它们可以被处理。我仍然想知道是否有其他方法来处理此问题。这不仅是您自己的问题可以接受的,而且是值得鼓励的。请随时发布答案我的感觉更糟,为了等待,我不得不:尝试{Tasks.WaitAll(Tasks);}catch(OperationCanceledException){try{Tasks.WaitAll(Tasks);}catch(aggregateeexception){Tasks.WaitAll(Tasks);}然后进行处置……不确定为什么,但这似乎有效。