Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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# 向现有WaitAll添加更多任务_C#_Multithreading_Task Parallel Library - Fatal编程技术网

C# 向现有WaitAll添加更多任务

C# 向现有WaitAll添加更多任务,c#,multithreading,task-parallel-library,C#,Multithreading,Task Parallel Library,假设我有一个Tasks的集合,我将在上面WaitAll()。 假设,在它们全部完成之前,我想向集合中添加更多的任务,并且我想继续等待,直到它们全部完成。我可能会在结束前增加更多的任务,等等 我可以用第三方物流吗?还是我必须手动滚动我自己的线程管理?(恶心!) WaitAll()作用于Task[]所以我不能只打开一个列表,我调用.ToArray()打开,因为这样等待就不会知道添加了什么新任务了 关于WaitAny()的类似问题也适用。以下是WaitAll的一个解决方案: 假设您有以下列表来保存任务

假设我有一个
Task
s的集合,我将在上面
WaitAll()
。 假设,在它们全部完成之前,我想向集合中添加更多的任务,并且我想继续等待,直到它们全部完成。我可能会在结束前增加更多的任务,等等

我可以用第三方物流吗?还是我必须手动滚动我自己的线程管理?(恶心!)

WaitAll()
作用于
Task[]
所以我不能只打开一个
列表
,我调用
.ToArray()
打开,因为这样等待就不会知道添加了什么新任务了


关于
WaitAny()
的类似问题也适用。

以下是
WaitAll
的一个解决方案:

假设您有以下列表来保存任务:

List<Task> tasks = new List<Task>();
只需确保在向列表中添加任务时锁定列表,如下所示:

lock (tasks)
{
    tasks.Add(...
}

顺便问一下,您为什么要同步等待任务而不是异步等待任务(您使用的是
WaitAll
而不是
whalll
)?

如果您想同步等待某个任务,然后再等待其他任务,您需要取消原来的等待并启动一个新的等待。按照开始时的等待方式进行初始等待,然后当需要添加更多任务时,将其添加到当前任务列表中,并发出取消信号,从而重新启动等待

public class MutableTaskWaiter
{
    private List<Task> _tasks = new List<Task>();
    private CancellationTokenSource _cts;

    public IEnumerable<Task> Tasks
    {
        get
        {
            lock (_tasks)
            {
                return _tasks.ToArray();
            }
        }
    }

    public void WaitAll(IEnumerable<Task> tasks)
    {
        WaitMoreTasks(tasks);

        do
        {
            try
            {
                _cts = new CancellationTokenSource();
                Task.WaitAll(_tasks.ToArray(), _cts.Token);
            }
            catch (OperationCanceledException)
            {
                // start over and wait for new tasks
            }
        }
        while (_cts.IsCancellationRequested);
    }


    public void WaitAny(IEnumerable<Task> tasks)
    {
        WaitMoreTasks(tasks);

        do
        {
            try
            {
                _cts = new CancellationTokenSource();
                Task.WaitAny(_tasks.ToArray(), _cts.Token);
            }
            catch (OperationCanceledException)
            {
                // start over and wait for new tasks
            }
        }
        while (_cts.IsCancellationRequested);
    }


    public void WaitMoreTasks(IEnumerable<Task> tasks)
    {
        lock (_tasks)
        {
            _tasks.AddRange(tasks);
            if (_cts != null)
            {
                // signal the wait to restart with the updated task list
                _cts.Cancel();
            }
        }
    }
}
公共类mutableTaskWater
{
私有列表_tasks=新列表();
私有取消令牌源;
公共可数任务
{
得到
{
锁定(_任务)
{
return_tasks.ToArray();
}
}
}
公共void WaitAll(IEnumerable任务)
{
WaitMoreTasks(任务);
做
{
尝试
{
_cts=新的CancellationTokenSource();
Task.WaitAll(_tasks.ToArray(),_cts.Token);
}
捕获(操作取消异常)
{
//重新开始并等待新任务
}
}
while(_cts.iscancellationrequest);
}
public void WaitAny(IEnumerable任务)
{
WaitMoreTasks(任务);
做
{
尝试
{
_cts=新的CancellationTokenSource();
Task.WaitAny(_tasks.ToArray(),_cts.Token);
}
捕获(操作取消异常)
{
//重新开始并等待新任务
}
}
while(_cts.iscancellationrequest);
}
公共任务(IEnumerable任务)
{
锁定(_任务)
{
_tasks.AddRange(任务);
如果(_cts!=null)
{
//用更新的任务列表发出等待重新启动的信号
_cts.Cancel();
}
}
}
}

当然,如果你长时间添加任务,并且最初有一些短期任务,你仍然需要处理WaitAll场景中的种族条件。e、 g.如果我的初始任务列表在5秒后完成,我不能在10秒后将新任务添加到等待列表中,因为我已经在等待了。

Re wait/When,因为这是在升级庞大的传统代码库的核心线程(替换
QueueUserWorkItem
+
ManualResetEvent
-基于信号量)让异步和/或回调扩展到整个代码库的其余部分是站不住脚的。
public class MutableTaskWaiter
{
    private List<Task> _tasks = new List<Task>();
    private CancellationTokenSource _cts;

    public IEnumerable<Task> Tasks
    {
        get
        {
            lock (_tasks)
            {
                return _tasks.ToArray();
            }
        }
    }

    public void WaitAll(IEnumerable<Task> tasks)
    {
        WaitMoreTasks(tasks);

        do
        {
            try
            {
                _cts = new CancellationTokenSource();
                Task.WaitAll(_tasks.ToArray(), _cts.Token);
            }
            catch (OperationCanceledException)
            {
                // start over and wait for new tasks
            }
        }
        while (_cts.IsCancellationRequested);
    }


    public void WaitAny(IEnumerable<Task> tasks)
    {
        WaitMoreTasks(tasks);

        do
        {
            try
            {
                _cts = new CancellationTokenSource();
                Task.WaitAny(_tasks.ToArray(), _cts.Token);
            }
            catch (OperationCanceledException)
            {
                // start over and wait for new tasks
            }
        }
        while (_cts.IsCancellationRequested);
    }


    public void WaitMoreTasks(IEnumerable<Task> tasks)
    {
        lock (_tasks)
        {
            _tasks.AddRange(tasks);
            if (_cts != null)
            {
                // signal the wait to restart with the updated task list
                _cts.Cancel();
            }
        }
    }
}