6

How to Wait for Task in C# thread programming

 3 years ago
source link: https://www.dotnetforall.com/wait-for-task-csharp-programming/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Feb 03 2017

How to Wait for Task in C# thread programming

In this article I will discuss the various ways by which we can wait for task or multiple tasks completion in C#. There are many ways in which we can achieve the same in C# programming language.

Before going forward if you want to know more about tasks parallel library you can check the following articles.

Why to wait for Task?

Tasks are used for asynchronous programming. A long running operation is performed using the asynchronous call and not blocking the current thread. But suppose we have issued a number of asynchronous calls and we want to perform some operation depending on the result of all these calls or may be the result of the any of the calls which executed first.

Wait for Single Task

To wait for single task we can use the Wait method of the Task object. Check the below code.

Task output = Task.Factory.StartNew(LongRunningOperation); output.Wait(); Console.WriteLine(output.Status);
Task output = Task.Factory.StartNew(LongRunningOperation); output.Wait(); Console.WriteLine(output.Status);

The above code I am executing the LongRunningOperation which waits for some time duration. The task object which is being returned in turn is used to wait for the task to complete. Once completed, I write the status of the task on the console. The status can be RanToCompletion, Cancelled, Faulted based on the operation in the method.

The other implicit way to wait for a single task is to check for the result. But in this case we should use the generic task. The long running method should call a method which has a return type. Check the C# code below

static void Main(string[] args)
Task output = Task.Factory.StartNew(LongRunningOperation);
Console.WriteLine(output.Result);
private static int LongRunningOperation()
Thread.Sleep(2000);
return 2000;
        static void Main(string[] args)
        {
            Task output = Task.Factory.StartNew(LongRunningOperation);
            Console.WriteLine(output.Result);
        }
        private static int LongRunningOperation()
        {
            Thread.Sleep(2000);
            return 2000;
        }

In the above code the result i.e. 2000 will be displayed after 2 seconds.

Wait for Multiple Tasks

There can be chance that we have to issue multiple threads using tasks and wait for all of them. The below code handles this kind of scenario using Task.WaitAll. WaitAll will wait for all the tasks to complete.

Task<int> output = Task.Factory.StartNew(LongRunningOperation);
Task<int> output1 = Task.Factory.StartNew(LongRunningOperation);
Task<int> output2 = Task.Factory.StartNew(LongRunningOperation);
Task<int> output3 = Task.Factory.StartNew(LongRunningOperation);
Task.WaitAll(output, output1, output2, output3);</int></int></int></int>
            Task output = Task.Factory.StartNew(LongRunningOperation);
            Task output1 = Task.Factory.StartNew(LongRunningOperation);
            Task output2 = Task.Factory.StartNew(LongRunningOperation);
            Task output3 = Task.Factory.StartNew(LongRunningOperation);
            Task.WaitAll(output, output1, output2, output3);

Though I am calling the same method in all the tasks, but it can be different methods. The second parameter is a collection of Task object. I  have found this way of waiting the Task very helpful if we have to call a Web Api which exposes an async method. I can issue hundreds of call to the web api and wait for all of them to complete before going to further processing.

The other way to wait for the multiple tasks is using WhenAll  method of the Task class. This method will return a task which will complete when all the task objects in the array have been completed.

Task<int> output = Task.Factory.StartNew(LongRunningOperation);
Task<int> output1 = Task.Factory.StartNew(LongRunningOperation);
Task<int> output2 = Task.Factory.StartNew(LongRunningOperation);
Task<int> output3 = Task.Factory.StartNew(LongRunningOperation);
var allTask = Task.WhenAll(output, output1, output2, output3);
if (allTask.IsCompleted)
foreach (var item in allTask.Result)
Console.Write(string.Format("result {1}", item));
}</int></int></int></int>
  Task output = Task.Factory.StartNew(LongRunningOperation);
            Task output1 = Task.Factory.StartNew(LongRunningOperation);
            Task output2 = Task.Factory.StartNew(LongRunningOperation);
            Task output3 = Task.Factory.StartNew(LongRunningOperation);
            var allTask = Task.WhenAll(output, output1, output2, output3);
            if (allTask.IsCompleted)
            {
                foreach (var item in allTask.Result)
                {
                    Console.Write(string.Format("result {1}", item));
                }
            }

And if in case if you want to wait for only a single task to complete. You have to use WaitAny method of the Task class. The parameter of the WaitAny method is the same task collection.

This can be useful in scenario where we want to run any of the task. For example, if you have a collection of some object and you want to search for any particular item in that collection. In that case you can divide the list equal to the number of cores in the machine.  And perform a search operation on each part by sending each chunk part to the task.

Now suppose if I have quad core machine, in that case I will have four tasks running in parallel. And any task completing first should have the searched item.

In the below C# code I have four list which I am passing as argument to the LongRunningOperation method. And I am using WaitAny to wait for the first task to complete and get the task from the task list using the index.

List<string> list1 = new List<string>();
List<string> list2 = new List<string>();
List<string> list3 = new List<string>();
List<string> list4 = new List<string>();
Task<string> output = Task.Factory.StartNew(() => LongRunningOperation(list1));
Task<string> output1 = Task.Factory.StartNew(() => LongRunningOperation(list2));
Task<string> output2 = Task.Factory.StartNew(() => LongRunningOperation(list3));
Task<string> output3 = Task.Factory.StartNew(() => LongRunningOperation(list4));
Task[] taskList = { output, output1, output2, output3 };
var taskCompleted = Task.WaitAny(taskList);
Task completedTask = taskList[taskCompleted];
private static string LongRunningOperation(List<string> list)
return null;
//find the element in the list }
}</string></string></string></string></string></string></string></string></string></string></string></string></string>
  List list1 = new List();
            List list2 = new List();
            List list3 = new List();
            List list4 = new List();
            Task output = Task.Factory.StartNew(() => LongRunningOperation(list1));
            Task output1 = Task.Factory.StartNew(() => LongRunningOperation(list2));
            Task output2 = Task.Factory.StartNew(() => LongRunningOperation(list3));
            Task output3 = Task.Factory.StartNew(() => LongRunningOperation(list4));
            Task[] taskList = { output, output1, output2, output3 };
            var taskCompleted = Task.WaitAny(taskList);
            Task completedTask = taskList[taskCompleted];

  private static string LongRunningOperation(List list)
        {
            return null;
            //find the element in the list }
        }

Conclusion:

In this article I have discussed many ways to wait for task and multiple tasks. I have also discussed the scenarios where these ways can be used to make most out of the tasks to improve the performance of the applications.

References:

My Learning Resource

Excel your system design interview

Like this:

Loading...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK