简体   繁体   English

等待所有线程

[英]Wait for all Threads

I have a little problem with Threads in this code.. 我在这段代码中有一些Threads的问题..

I just want to run a lot of tasks together, and continue when all of them finish. 我只想一起完成很多任务,并在所有任务完成后继续。

while (true)
{
    //   Run tasks together:
    foreach (object T in objectsList)
    {
        if (T.something>0)
            var task = Task.Factory.StartNew(() => T.RunObject());
            task.ContinueWith(delegate { ChangeObject(T, 1); }, TaskContinuationOptions.NotOnFaulted);
    }
    //   <-- Here I want to wait for all the task to be finish.
    //   I know its task.Wait() but how to waitAll()?
    System.Threading.Thread.Sleep(this.GetNextTime()); 
    var RefreshObjects = new Task(loadObjectsList); RefreshObjects .Start(); RefreshObjects.Wait();
}

I don't know how many objects will be in objectsList and I don't know if T.something will be > 0. so I can't just use: 我不知道在objectsList多少个对象,我不知道T.something是否> 0所以我不能只使用:

Task[] Tasks = new Task[objectsList.count()]
for (int T=0; T<objectsList.count(); ++T)
{
    if (objectsList[T].something>0)
        var task = Task.Factory.StartNew(() => objectsList[T].RunObject());
        task.ContinueWith(delegate { ChangeObject(objectsList[T], 1); }, ...);
}
Task.WaitAll(Tasks);

Because Tasks will contains nulls when objectsList[T].something!>0 ... 因为在对象objectsList[T].something!>0时, Tasks将包含空值...

Thanks for any advice! 谢谢你的建议!

Just switch the condition and create a List of tasks only for the objects which matches your criteria. 只需切换条件并仅为符合条件的对象创建任务列表。

var tasks = objectsList
            .Where(x => x.Something() > 0)
            .Select(x => {
                            var task = Task.Factory.StartNew(() => x.RunObject());
                            task.ContinueWith(t => ChangeObject(....));
                            return task;
                         })
            .ToArray();

    Task.WaitAll(tasks);

Your code sample just waits for RunObject() to complete! 您的代码示例只是等待RunObject()完成! If this is desired skip the rest of my answer. 如果需要,请跳过我的其余部分。 If you want to wait for the continuation to complete, too you can use this 如果你想等待继续完成,你也可以使用它

var tasks = objectsList
            .Where(x => x.Something() > 0)
            .Select(x => Task.Factory.StartNew(() => x.RunObject()).ContinueWith(t => ChangeObject(....)))
            .ToArray();

    Task.WaitAll(tasks);

because ContinueWith generates a new Task. 因为ContinueWith生成一个新任务。

If objectsList implements IEnumerable, (as an array does), (And there are less than 64 objects in the list), you can use this: 如果objectsList实现IEnumerable,(就像数组一样),(并且列表中的对象少于64个),您可以使用:

public delegate void SyncDelegatesInParallelDelegate<in T>(T item);
public static class ParallelLinqExtensions
{
    public static void SyncDelegatesInParallel<T>(
        this IEnumerable<T> list, 
        SyncDelegatesInParallelDelegate<T> action)
    {
        var foundCriticalException = false;
        Exception exception = null;
        var waitHndls = new List<WaitHandle>();

        foreach (var item in list)
        {
            // Temp copy of session for modified closure
            var localItem = item;
            var txEvnt = new ManualResetEvent(false);

            // Temp copy of session for closure
            ThreadPool.QueueUserWorkItem(
                 depTx =>
                 {
                     try { if (!foundCriticalException) action(localItem); }
                     catch (Exception gX) 
                     { exception = gX; foundCriticalException = true; }
                     finally { txEvnt.Set(); }
                 }, null);
            waitHndls.Add(txEvnt);
        }
        if (waitHndls.Count > 0) WaitHandle.WaitAll(waitHndls.ToArray());
        if (exception != null) throw exception;
    }
}

you would call it like this 你会这样称呼它

 objectsList.SyncDelegatesInParallel(delegate { ChangeObject(T, 1);});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM