FreeVice
FreeVice

Reputation: 2697

How to run some methods async and catch end of them?

I need to generate a report once a number of methods have completed. But in this sample they are not asynchronous.

    static void Main(string[] args)
    {
        TaskMan();
    }

    async static void TaskMan()
    {
        Task t1 = m1();
        Task t2 = m2();
        await Task.WhenAll(t1, t2);
        Console.WriteLine("Complete");
    }

    async static Task m1()
    {
        decimal result = 0;
        for (int n = 1; n < 100000000; n++)
        {
            result += n;
        }
        Console.WriteLine(result);
    }

    async static Task m2()
    {
        decimal result = 0;
        for (int n = 1; n < 100000000; n++)
        {
            result += n;
        }
        Console.WriteLine(result);
    }

How to do them really async?

Upvotes: 2

Views: 203

Answers (4)

Adam Houldsworth
Adam Houldsworth

Reputation: 64557

Firstly, it isn't running asynchronously because in these lines you are actually calling the methods in a non-asynchronous manner:

Task t1 = m1();
Task t2 = m2();

This is because you neither await the call at this point, nor await internally. The net effect is a standard method call.

Secondly, async doesn't necessarily mean on another thread.

The following amendments will start new tasks and associate them with promises you can use to monitor their completion, then you WhenAll as before in an asynchronous manner. Do note that the task will start on StartNew, not on WhenAll.

async static void TaskMan()
{
    Task t1 = Task.Run((Action)m1);
    Task t2 = Task.Run((Action)m2);

    await Task.WhenAll(t1, t2);
    Console.WriteLine("Compete");
}

static void m1()
{
    decimal result = 0;
    for (int n = 1; n < 100000000; n++)
    {
        result += n;
    }
    Console.WriteLine(result);
}

static void m2()
{
    decimal result = 0;
    for (int n = 1; n < 100000000; n++)
    {
        result += n;
    }
    Console.WriteLine(result);
}

Unfortunately, we are not demonstrating the benefit of waiting asynchronously as we aren't doing anything in the mean time.

Upvotes: 5

Stephen Cleary
Stephen Cleary

Reputation: 457422

There are two problems with your code.

First, as others have pointed out, async does not mean "run on a background thread". All that async does is enable a compiler-generated state machine that handles the await keyword. So async without await is useless. As @svick pointed out, don't ignore the compiler warnings! I have an async intro on my blog that you may find helpful. You should be using Task.Run to explicitly place work on a background thread.

The second problem is that you're starting asynchronous work but then returning from Main before giving it a chance to complete. If this is a simple proof-of-concept, then you could call Wait on your top-level task (normally, you would never want to mix blocking and asynchronous code like this as I describe in my MSDN article, but the Main method of a console application is an exception to that rule).

static void Main(string[] args)
{
    TaskManAsync().Wait();
}

static async Task TaskManAsync()
{
    Task t1 = Task.Run(() => m1());
    Task t2 = Task.Run(() => m2());
    await Task.WhenAll(t1, t2);
    Console.WriteLine("Complete");
}

static void m1()
{
    decimal result = 0;
    for (int n = 1; n < 100000000; n++)
    {
        result += n;
    }
    Console.WriteLine(result);
}

static void m2()
{
    decimal result = 0;
    for (int n = 1; n < 100000000; n++)
    {
        result += n;
    }
    Console.WriteLine(result);
}

If this is more than a proof-of-concept and you are actually intending to create an asynchronous Console application, then I recommend you use a single-threaded async-compatible context as I describe on my blog.

Upvotes: 2

Louis van Tonder
Louis van Tonder

Reputation: 3710

Use threading and create a separate thread for each function. You can be notified when the thread completes. Note that you cannot update the UI from a function called in a thread. You have to use other means of updating the UI itself from a thread, which might be a new question.

Your console.writeline should work tho.

Upvotes: -4

Rafal
Rafal

Reputation: 12639

The async keyword does not mean that method will be run in a asynchronous manner. I believe that you have VS report warnings on those methods as they don't do any awaiting. To run in a thread you should write:

return Task.Factory.StartNew(()=>
    decimal result = 0;
    for (int n = 1; n < 100000000; n++)
    {
        result += n;
    }
    Console.WriteLine(result);
});

this will do what you want.

Upvotes: 1

Related Questions