Reputation: 460
I've tried this...
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;
}
and this...
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;
}
and this too...
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;
}
I also tried Spawn Multiple Threads for work then wait until all finished
I still get a null in one of the arraylist items in allObjectAttributes.
However, when I do
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;
}
I never get a null item in the arraylist items.
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; }
Upvotes: 5
Views: 5953
Reputation: 9587
Slightly improved by using a thread-safe collection (.NET 4.0 compatible):
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;
Alternative approach: use Task.Result
once all tasks have completed (thread-safe collection no longer required as only one thread modifies 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;
Significantly improved by using Task.WhenAll
(.NET 4.5 only):
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;
*Note: I used object
as the generic parameter as you left the return type of GetObjectAttributes
unspecified.
Upvotes: 8
Reputation: 10152
Task.WaitAll() that you used in your first example should work as intended. However, I suspect that the issue you're having has to do more with thread safety of the collection you use, ArrayList, rather than the fact that the completion of all task is not waited upon. ArrayList offers no thread safety, so you should look at other ways, either through use of a locking mechanism or through the use of a thread-safe collection, such as ConcurrentBag (https://msdn.microsoft.com/en-us/library/dd381779(v=vs.110).aspx).
Upvotes: 0