簡體   English   中英

C#等待所有線程完成執行

[英]C# Wait Till All Threads Complete Execution

我試過這個......

public ArrayList GetAllObjectAttributes()
    {
        List<Task> taskList = new List<Task>();
        ArrayList allObjectAttributes = new ArrayList();
        taskList.Add(Task.Factory.StartNew(() => { allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Folder));}));
        taskList.Add(Task.Factory.StartNew(() => { allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.XMLFile)); }));
        taskList.Add(Task.Factory.StartNew(() => { allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.TextFile)); }));
        taskList.Add(Task.Factory.StartNew(() => { allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Parent)); }));
        Task.WaitAll(taskList.ToArray());
        return allObjectAttributes;
    }

和這個...

public ArrayList GetAllObjectAttributes()
    {
        Thread[] threads = new Thread[4];
        ArrayList allObjectAttributes = new ArrayList();
        threads[0] = new Thread(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Folder)));
        threads[1] = new Thread(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.XMLFile)));
        threads[2] = new Thread(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.TextFile)));
        threads[3] = new Thread(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Parent)));

        foreach(Thread thread in threads)
        {
            thread.Start();
            thread.Join();
        }
        return allObjectAttributes;
    }

這也是......

public ArrayList GetAllObjectAttributes()
    {
        Thread[] threads = new Thread[4];
        ArrayList allObjectAttributes = new ArrayList();
        threads[0] = new Thread(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Folder)));
        threads[1] = new Thread(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.XMLFile)));
        threads[2] = new Thread(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.TextFile)));
        threads[3] = new Thread(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Parent)));

        foreach(Thread thread in threads)
        {
            thread.Start();
        }
        while(threads[0].IsAlive || threads[1].IsAlive || threads[2].IsAlive || threads[3].IsAlive)
        {
            Thread.Sleep(500);
        }
        return allObjectAttributes;
    }

我也試過Spawn Multiple Threads工作然后等到所有完成

我仍然在allObjectAttributes中的一個arraylist項中得到null。

但是,當我這樣做的時候

public ArrayList GetAllObjectAttributes()
    {
        ArrayList allObjectAttributes = new ArrayList();
        allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Folder)));
        allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.XMLFile)));
        allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.TextFile)));
        allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Parent)));
        return allObjectAttributes;
    }

我從來沒有在arraylist項目中獲得null項。

  1. 等到所有線程完成后我做錯了什么?
  2. 任何其他建議,以便只有在所有4個線程完成執行后才返回arraylist。
private List GetObjectAttributes(TreeViewAttrs tv)
{
    List objectAttributes = new List();
    string command = "COMMAND_TO_EXECUTE";
    if (command != "")
    {
        List results = RunCommand(command);
        if (results == null) { return null; }
        if (results.Count > 0)
        {
            foreach (string result in results)
            {
                if (!result.Contains("" + tv + ""))
                {
                    string[] res = reformatResponseString(result); //reformat the strings as per custom structure
                    if (res != null) { objectAttributes.Add(res); }
                }
            }
            return objectAttributes;
        }
    }
    return null;
}

使用線程安全集合(.NET 4.0兼容)稍微改進:

List<Task> taskList = new List<Task>();
ConcurrentBag<object> allObjectAttributes = new ConcurrentBag<object>();

taskList.Add(Task.Factory.StartNew(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Folder))));
taskList.Add(Task.Factory.StartNew(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.XMLFile))));
taskList.Add(Task.Factory.StartNew(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.TextFile))));
taskList.Add(Task.Factory.StartNew(() => allObjectAttributes.Add(GetObjectAttributes(TreeViewAttrs.Parent))));

Task.WaitAll(taskList.ToArray());

return allObjectAttributes;

替代方法:完成所有任務后使用Task.Result (不再需要線程安全集合,因為只有一個線程修改了ArrayList ):

Task<object>[] taskList = {
    Task.Factory.StartNew(() => (object)GetObjectAttributes(TreeViewAttrs.Folder)),
    Task.Factory.StartNew(() => (object)GetObjectAttributes(TreeViewAttrs.XMLFile)),
    Task.Factory.StartNew(() => (object)GetObjectAttributes(TreeViewAttrs.TextFile)),
    Task.Factory.StartNew(() => (object)GetObjectAttributes(TreeViewAttrs.Parent))
};

Task.WaitAll(taskList);

ArrayList allObjectAttributes = new ArrayList();

foreach (Task<object> task in taskList) {
    allObjectAttributes.Add(task.Result);
}

return allObjectAttributes;

使用Task.WhenAll (僅限.NET 4.5) 顯着改進:

object[] allObjectAttributes = await Task.WhenAll(
    Task.Run(() => GetObjectAttributes(TreeViewAttrs.Folder)),
    Task.Run(() => GetObjectAttributes(TreeViewAttrs.XMLFile)),
    Task.Run(() => GetObjectAttributes(TreeViewAttrs.TextFile)),
    Task.Run(() => GetObjectAttributes(TreeViewAttrs.Parent))
);

return allObjectAttributes;

*注意:我使用了object作為通用參數,因為你保留了未指定的GetObjectAttributes的返回類型。

您在第一個示例中使用的Task.WaitAll()應該按預期工作。 但是,我懷疑你所擁有的問題必須使用你使用的集合的線程安全性,ArrayList,而不是等待所有任務的完成這一事實。 ArrayList沒有線程安全性,所以你應該通過使用鎖定機制或通過使用線程安全的集合來查看其他方法,例如ConcurrentBag( https://msdn.microsoft.com/en-us/ library / dd381779(v = vs.110).aspx )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM