Reputation: 2697
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
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
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
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
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