Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Wait Till All Threads Complete Execution

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.

  1. What am i doing wrong to wait until all threads complete?
  2. Any other advise, so that the arraylist is returned only after all the 4 threads complete execution.
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;
}
like image 566
Vinay Sathyanarayana Avatar asked Dec 09 '15 06:12

Vinay Sathyanarayana


People also ask

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


1 Answers

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.

like image 50
Kirill Shlenskiy Avatar answered Oct 07 '22 03:10

Kirill Shlenskiy