C# Async example

Hi,

I am after a simple bit code that uses async and await.

The key thing I am looking for then a way I can test the function has finished doing its work.

So the calling routine eg - so here is some pseudo code below;

Bool finished = false;
Test1();   // the async call
While (true)
   {
      If (test1.finished == true)
          {
             Break;
          }
      Thread.sleep(2000);
    }

So something simple based on the above would be great :)

Thanks,
Ward
LVL 1
whorsfallAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

käµfm³d 👽Commented:
First of all, the whole point of async/await is that you don't have to tie up the processor waiting for work to complete. Your loop is doing just that. async/await is intended for I/O-bound operations. You should be returning Tasks from your async methods, which you can then continue on once they finish. Your async methods should internally be working with the async methods provided by the Framework (e.g. HttpClient.GetAsync).

Let's say that your Test1 method download this very page from EE. You might have this as the implementation:

class YourClass
{
    async public Task<string> Test1()
    {
        string html = string.Empty;

        using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
        {
            System.Net.Http.HttpResponseMessage response = await client.GetAsync("http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_28686082.html");

            html = await response.Content.ReadAsStringAsync();                
        }

        return html;
    }
}

Open in new window


You'll note above that I use async/await, but that I use it in conjunction with methods that are designed to be asynchronous. The way that await works is that when your code hits a line with await in it, that line is fired off, and execution immediately returns to the caller. For the above, that means that my first await is sent off, but the second one is not hit right away. Once the runtime receives notice that the async call has returned, the continuation that was set up for you (behind the scenes) is executed, and control resumes at the next line above. In this case, there is another await call, so again, the call is fired off, and execution returns to the caller. Once the runtime is notified, the code will resume with the next line, which at this point is the return statement.

The calling code could look like this:

class Program
{
    static void Main(string[] args)
    {
        YourClass instance = new YourClass();

        Task t =  instance.Test1()
                          .ContinueWith(AfterDownload);

        t.Wait();

        Console.ReadKey();
    }

    private static void AfterDownload(Task<string> html)
    {
        Console.WriteLine(html.Result);
    }
}

Open in new window


The important thing to keep in mind with async/await is that everything will return a Task. Only event handlers--which aren't demonstrated above--should ever return void; anything else returns a Task.

As you can see above, I have saved off the Task that is returned by ContinueWith into a variable named "t". I need this so that I can call Wait in the next line. Since the method Test1 is async, the call will not block on either Test1 or ContinueWith. Therefore, in order to keep my program from terminating before the async operation is complete, I call Wait against the Task that I saved. Wait will block until the Task is complete.

The ContinueWith sets up a continuation. Once the Task that is created by Test1 is complete, the ContinueWith method will execute the delegate. In the above, the delegate points to the AfterDownload method. That means that once the entire async operation is complete, the AfterDownload method will be invoked, and the HTML that was downloaded will be output to the console window.

Keep in mind that I myself am very new to async/await, so I may have (inadvertently) overlooked some bits in the explanation. Also, keep in mind that async/await is handled a tad differently in Win Forms and ASP.NET. Much of the time, you don't have to explicitly call Wait on your tasks. The ASP.NET runtime, for example, has code within it that will wait on your task to complete before it returns to the client. In Win Forms, your event handlers drop back into the event loop, so your program isn't going to terminate before the Task has a chance to finish. In my example above, there is no (event) loop, so once all of the code in Main executes, the program is done. The call to Wait is how I prevented that from happening.
Minh Võ CôngCommented:
try use eventwaithandle class
using System;
using System.Threading;

public class Example
{
    // The EventWaitHandle used to demonstrate the difference 
    // between AutoReset and ManualReset synchronization events. 
    // 
    private static EventWaitHandle ewh;

    // A counter to make sure all threads are started and 
    // blocked before any are released. A Long is used to show 
    // the use of the 64-bit Interlocked methods. 
    // 
    private static long threadCount = 0;

    // An AutoReset event that allows the main thread to block 
    // until an exiting thread has decremented the count. 
    // 
    private static EventWaitHandle clearCount = 
        new EventWaitHandle(false, EventResetMode.AutoReset);

    [MTAThread]
    public static void Main()
    {
        // Create an AutoReset EventWaitHandle. 
        //
        ewh = new EventWaitHandle(false, EventResetMode.AutoReset);

        // Create and start five numbered threads. Use the 
        // ParameterizedThreadStart delegate, so the thread 
        // number can be passed as an argument to the Start  
        // method. 
        for (int i = 0; i <= 4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked. 
        // When multiple threads use a 64-bit value on a 32-bit 
        // system, you must access the value through the 
        // Interlocked class to guarantee thread safety. 
        // 
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Release one thread each time the user presses ENTER, 
        // until all threads have been released. 
        // 
        while (Interlocked.Read(ref threadCount) > 0)
        {
            Console.WriteLine("Press ENTER to release a waiting thread.");
            Console.ReadLine();

            // SignalAndWait signals the EventWaitHandle, which 
            // releases exactly one thread before resetting,  
            // because it was created with AutoReset mode.  
            // SignalAndWait then blocks on clearCount, to  
            // allow the signaled thread to decrement the count 
            // before looping again. 
            //
            WaitHandle.SignalAndWait(ewh, clearCount);
        }
        Console.WriteLine();

        // Create a ManualReset EventWaitHandle. 
        //
        ewh = new EventWaitHandle(false, EventResetMode.ManualReset);

        // Create and start five more numbered threads. 
        // 
        for(int i=0; i<=4; i++)
        {
            Thread t = new Thread(
                new ParameterizedThreadStart(ThreadProc)
            );
            t.Start(i);
        }

        // Wait until all the threads have started and blocked. 
        // 
        while (Interlocked.Read(ref threadCount) < 5)
        {
            Thread.Sleep(500);
        }

        // Because the EventWaitHandle was created with 
        // ManualReset mode, signaling it releases all the 
        // waiting threads. 
        //
        Console.WriteLine("Press ENTER to release the waiting threads.");
        Console.ReadLine();
        ewh.Set();

    }

    public static void ThreadProc(object data)
    {
        int index = (int) data;

        Console.WriteLine("Thread {0} blocks.", data);
        // Increment the count of blocked threads.
        Interlocked.Increment(ref threadCount);

        // Wait on the EventWaitHandle.
        ewh.WaitOne();

        Console.WriteLine("Thread {0} exits.", data);
        // Decrement the count of blocked threads.
        Interlocked.Decrement(ref threadCount);

        // After signaling ewh, the main thread blocks on 
        // clearCount until the signaled thread has  
        // decremented the count. Signal it now. 
        //
        clearCount.Set();
    }
}

Open in new window


https://msdn.microsoft.com/en-us/library/system.threading.eventwaithandle(v=vs.110).aspx

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.