Recently I try to learn about the new C# feature, async/await keywords for asynchronous programming. When I searched at web, I faced this example:
static void Main(string[] args)
{
Console.WriteLine("Task based APM demo");
// Call Exponnent() asynchronously.
// And immediately return the control flow.
// If I don't put a Task here, the program will sometimes
// terminate immediately.
Task t = new Task(async () =>
{
int result = await Program.Exponent(10);
// After the operation is completed, the control flow will go here.
Console.WriteLine(result);
});
t.Start();
Console.ReadKey();
}
static async Task<int> Exponent(int n)
{
Console.WriteLine("Task started");
return await TaskEx.Run<int>(() => 2 << (n - 1));
}
}
I have questions about it and about the manner that this statements act.
First as I understand an await expression used when we want release the process at that point and return to the caller context. But why this expression used this at the line which the Exponent method called at it? In fact what happen when the compiler faced this line of program?
And the letter question is, why the program use "TaskEx.Run" for returning the result in the body of Exponent method? Is it possible to use "return await (() => 2 << (n - 1));" only? How the compiler behaves with this line?
Thanks in advance
But why this expression used this at the line which the Exponent called at it?
I'm not sure what you mean by this question. await Task.Run<int>(() => 2 << (n - 1)); tells the compiler to suspend execution of the current method until the task completes. In terms of task, this is similar to:
Task.Run<int>(() => 2 << (n - 1)).ContinueWith(t=>return t.Result);
But, of course, you cannot return from a continuation. The async keyword tells the compiler not only that there could be one or more await operators in the method, but set's up a state machine to manage the different state transitions starting and returning from asynchronous operations. As well, this could affect how the method is executed in relationship to being asynchronous to the caller.
As to the Task used in Main: you can't await a method call in Main, so, I assume the Task is used to still use the await operator. But, it seems redundant. I would probably simply have another method to use await:
static async void Method()
{
Console.WriteLine(await Exponent(10));
}
Then re-write Main:
static void Main(string[] args)
{
Method();
Console.ReadLine();
}
But, I don't know the reasons behind why the code was originally written that way or even if there was a real purpose.
Is it possible to use "return await (() => 2 << (n - 1));"
It is not possible to write this line of code because nothing asynchronous is being performed. () => 2 << (n - 1) neither returns a Task object not has an GetAwaiter method associated with it; so, it can be executed asynchronously. thus, it can't be "awaited".
Related
** I've summarised this question at the bottom with an edit **
This has been asked before but I think my circumstances are different.
I am processing multiple requests simultaneously.
This is my code to do that, it runs in a loop. I've removed a bit of code that handles the taskAllocated variable for brevity.
while (!taskAllocated)
{
lock (_lock)
{
// Find an empty slot in the task queue to insert this task
for (i = 0; i < MaxNumTasks; i++)
{
if (_taskQueue[i] == null)
{
_taskQueue[i] = Task.Run(() => Process());
_taskQueue[i].ContinueWith(ProcessCompleted);
break;
}
}
}
}
Process is a typical async Task Process() { CpuIntensiveStuff(); } method.
I've been running the above code, and it has been working fine. It multithreads nicely. Whenever an item comes in, it will find an empty slot in the task queue, and kick it off. When the task completes, the ProcessCompleted method runs, and frees up the slot.
But then I thought, shouldn't I be using await inside my Task.Run? Something like:
_taskQueue[i] = Task.Run(async () => await Process());
After thinking about it, I'm not sure. ContinueWith triggers correctly, when the task has completed, so perhaps it's not necessary.
I ask because I wanted to monitor and log how long each task takes to complete.
So Instead of Process(), I would make another method like:
async Task DoProcess()
{
var sw = Stopwatch.StartNew();
Process();
sw.Stop();
Log(sw.ElapsedMilliseconds);
}
And it occurred to me that if I did that, I wasn't sure if I'd need to await Process(); or not, in addition to not knowing if I should await inside the Task.Run()
I'm in a bit of a tizz about this. Can anyone offer guidance?
Edit:
To summarise:
If Somemethod is:
void SomeMethod() { }
Then
Task.Run(() => SomeMethod()); is great, calls SomeMethod on a new 'thread' (not technically, but you know what I mean).
However, my SomeMethod is actually:
async Task SomeMethod() { }
Do you need to do anything special with Task.Run()?
My code, I am not, I am just straight up ignoring that it's an async Task, and that seems to work:
Task.Run(() => SomeMethod()); // SomeMethod is async Task but I am ignoring that
But I'm not convinced that it a) should work or b) is a good idea. The alternative could be to do:
Task.Run(async() => await SomeMethod());
But is there any point? And this is compounded by the fact I want to really do:
Task.Run(() =>
{
someCode();
var x = startTimer();
SomeMethod();
var y = stopTimer();
someMoreCode()
});
but without await I'm not sure it will wait for somemethod to finish and the timer will be wrong.
Things become more clear if you do not use anonymous methods. For example,
Task.Run(() => Process())
is equivalent to this:
Task.Run(DoSomething);
Task DoSomething() {
return Process();
}
Whereas
Task.Run(async () => await Process())
is equivalent to this:
Task.Run(DoSomething);
async Task DoSomething() {
await Process();
}
In most cases, there is no functional difference between return SomethingThatReturnsATask() and return await SomethingThatReturnsATask(), and you usually want to return the Task directly and not use await (for reasons described here). When used inside Task.Run, things could easily go bad if the .NET team didn't have your back.
It is important to note that asynchronous methods start running on the same thread just like any other method. The magic happens at the first await that acts on an incomplete Task. At that point, await returns its own incomplete Task. That's important - it returns, with a promise to do the rest later.
This could have meant that the Task returned from Task.Run would complete whenever Process() returns a Task. And since Process() returns a Task at the first await, that would happen when it has not yet totally completed.
The .NET team has your back
That is not the case however, because Task.Run has a specific overload for when you give it a method returning a Task. And if you look at the code, it returns a Task *that is tied to the Task you return.
That means that the Task returned from Task.Run(() => Process()) will not complete until the Task returned from Process() has completed.
So your code is fine the way it is.
I created a simple example to understand async/await in C#.
class Program
{
static void Main(string[] args)
{
var t = BarAsync();
Console.WriteLine("Main");
}
private static async Task BarAsync()
{
Console.WriteLine("This happens before await");
int i = await QuxAsync();
Console.WriteLine("This happens after await. This result of await is " + i);
}
private static Task<int> QuxAsync()
{
int c = 0;
for (int i = 0; i < int.MaxValue; i++)
{
c++;
}
Console.WriteLine("in the middle processing...");
return Task.FromResult(c);
}
}
So the program prints This happens before await first then count the value from a return method. Afterwards it prints the result.
It looks good. My question is that since await doesn't block the thread that evaluates the async method. My understanding is if the async takes a long time it will return to its calling method.
For my example, because QuxAsync() takes a long time, the code
Console.WriteLine("Main");
is not blocked and will be evaluated very soon.
I think the print order should be
This happens before await
Main
in the middle processing...
This happens after await. This result of await is 2147483647
However it is not, why?
I'll second (third?) others' recommendations that you continue reading and learning about async. I'm partial to my own async intro, but these days there are a number of good ones out there.
My question is that since await doesn't block the thread that evaluates the async method. My understanding is if the async takes a long time it will return to its calling method.
This is the part that is wrong. Asynchrony has absolutely nothing to do with how long something takes.
There's two pieces of knowledge missing, both covered in my async intro.
First: await works by first checking its argument. If it is already completed, then await continues executing - synchronously.
Second: every method is called synchronously. Including async methods. The only time asynchrony happens is when an async method has an await whose argument is not already completed; in that case, that async method returns an incomplete task.
Putting both of these together should explain why your code actually runs synchronously.
For the past several days, I've been trying to figure out why my async method is not working and its a very simple piece of code.
public class EntryPoint
{
static void Main()
{
RunTheTaskAsync();
//Console.ReadLine(); // if I add this to "hold" the finish of the project, I will see the result, without it I dont
}
public async static void RunTheTaskAsync()
{
Task<string> task = Concatenator('1', 200000);
Console.WriteLine("Heeeelllooooooo");
Console.WriteLine("I am running while Concatenator is concatenating in the background.");
Console.WriteLine("You will receive the results shortly");
string result = await task;
Console.WriteLine("Result is: " + result.Length);
}
public static Task<string> Concatenator(char characterToConcatenate, int count)
{
Console.WriteLine("Concatenating!");
return Task<string>.Factory.StartNew(() =>
{
string concatenatedString = "";
for (int i = 0; i < count; i++)
{
concatenatedString += characterToConcatenate;
}
return concatenatedString;
});
}
}
If I run it as it is in the example above, I never get to see the result, I only see the Console.WriteLine's and Press any key to continue.. after that no result.
If I uncomment the Console.ReadLine(); everything works as I am expecting it to work and I simply cant understand why!?! The same is true if I add some Thread.Sleep(xxx) or another piece of code that will take longer to execute than the "Concatenator" method.
Isn't this one of the issues that await should solve on its own, its kind of implied from its very name.
The way I understand it is:
The Task method starts executing on the background
We proceed with the 3 ConsoleWritelines in the async method
Since there is nothing else to do and the task is not completed yet, we get to the await line and we should await for the task
to be completed and then proceed with the rest of the code.
It works like this ONLY if have another piece of code inbetween that will take longer than the Task method to execute, or if I use the Console.ReadLine() and I just cant find an explanation about this!
I also have a secondary question regarding the syntax of my implementation. Is this the proper way to create a Task method? By using
public Task<T> SomeMethodName(some, args)
{
return Task<T>Factory.StartNew(() =>
{
somecode that returns T;
});
}
async voids (like your RunTheTaskAsync method) are "fire and forget". You can't track their progress and almost never want to use them.
Instead, make an async Task and await it:
static async Task Main()
{
await RunTheTaskAsync();
}
public static async Task RunTheTaskAsync()
{
...
}
For more details, see:
Async/Await - Best Practices in Asynchronous Programming
Note: Visual Studio prior to 2017 Update 3 does not support an async Main method. In that case, you have to manually await the Task:
static void Main()
{
RunTheTaskAsync().GetAwaiter().Wait();
}
About your second question (for the future: SO's policy is "one question per question"): Yes, Task.Factory.StartNew is correct if you need your task to run in a separate thread. Newer versions of .NET as offer Task.Run as a shortcut, see the following question for details:
What is the difference between Task.Run() and Task.Factory.StartNew()
The following code compiles and runs well. But where is the return statement for the Consumer() and Producer() methods?
class Program
{
static BufferBlock<Int32> m_buffer = new BufferBlock<int>(
new DataflowBlockOptions { BoundedCapacity = 10 });
public static async Task Producer() <----- How is a Task object returned?
{
while (true)
{
await m_buffer.SendAsync<Int32>(DateTime.Now.Second);
Thread.Sleep(1000);
}
}
public static async Task Consumer() <----- How is a Task object returned?
{
while (true)
{
Int32 n = await m_buffer.ReceiveAsync<Int32>();
Console.WriteLine(n);
}
}
static void Main(string[] args)
{
Task.WaitAll(Consumer(), Producer());
}
}
While your question states the obvious - the code compiles - and the other answers try to explain-by-example, I think the answer is best described in the following two articles:
"Above-the-surface" answer - full article is here: http://msdn.microsoft.com/en-us/magazine/hh456401.aspx
[...] C# and Visual Basic [...] giving enough hints to the compilers
to build the necessary mechanisms for you behind the scenes. The
solution has two parts: one in the type system, and one in the
language.
The CLR 4 release defined the type Task [...] to represent the
concept of “some work that’s going to produce a result of type T in
the future.” The concept of “work that will complete in the future but
returns no result” is represented by the non-generic Task type.
Precisely how the result of type T is going to be produced in the
future is an implementation detail of a particular task; [...]
The language half of the solution is the new await keyword. A regular
method call means “remember what you’re doing, run this method until
it’s completely finished, and then pick up where you left off, now
knowing the result of the method.” An await expression, in contrast,
means “evaluate this expression to obtain an object representing work
that will in the future produce a result. Sign up the remainder of the
current method as the callback associated with the continuation of
that task. Once the task is produced and the callback is signed up,
immediately return control to my caller.”
2.The under-the-hood explanation is found here: http://msdn.microsoft.com/en-us/magazine/hh456403.aspx
[...] Visual Basic and C# [...] let you express discontinuous
sequential code. [...] When the Visual Basic or C# compiler gets hold
of an asynchronous method, it mangles it quite a bit during
compilation: the discontinuity of the method is not directly supported
by the underlying runtime and must be emulated by the compiler. So
instead of you having to pull the method apart into bits, the compiler
does it for you. [...]
The compiler turns your asynchronous method into a statemachine. The
state machine keeps track of where you are in the execution and what
your local state is. [...]
Asynchronous methods produce Tasks. More specifically, an asynchronous
method returns an instance of one of the types Task or Task from
System.Threading.Tasks, and that instance is automatically generated.
It doesn’t have to be (and can’t be) supplied by the user code. [...]
From the compiler’s point of view, producing Tasks is the easy part.
It relies on a framework-supplied notion of a Task builder, found in
System.Runtime.CompilerServices [...] The builder lets the compiler
obtain a Task, and then lets it complete the Task with a result or an
Exception. [...] Task builders are special helper types meant only for
compiler consumption. [...]
[...] build up a state machine around the production and consumption
of the Tasks. Essentially, all the user logic from the original method
is put into the resumption delegate, but the declarations of locals
are lifted out so they can survive multiple invocations. Furthermore,
a state variable is introduced to track how far things have gotten,
and the user logic in the resumption delegate is wrapped in a big
switch that looks at the state and jumps to a corresponding label. So
whenever resumption is called, it will jump right back to where it
left off the last time.
when the method has no return statement its return type is Task. Have a look at the MSDN page of Async Await
Async methods have three possible return types: Task<TResult>, Task, void
if you need a Task you must specify the return statement. Taken from the MSDN page:
// TASK<T> EXAMPLE
async Task<int> TaskOfT_MethodAsync()
{
// The body of the method is expected to contain an awaited asynchronous
// call.
// Task.FromResult is a placeholder for actual work that returns a string.
var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());
// The method then can process the result in some way.
int leisureHours;
if (today.First() == 'S')
leisureHours = 16;
else
leisureHours = 5;
// Because the return statement specifies an operand of type int, the
// method must have a return type of Task<int>.
return leisureHours;
}
async keyword kind of tells compiler that the method body should be used as a Task body. In simple way we can say that these are equivalents to your examples:
public static Task Producer() <----- How is a Task object returned?
{
return Task.Run(() =>
{
while (true)
{
m_buffer.SendAsync<Int32>(DateTime.Now.Second).Wait();
Thread.Sleep(1000);
}
});
}
public static Task Consumer() <----- How is a Task object returned?
{
return Task.Run(() =>
{
while (true)
{
Int32 n = m_buffer.ReceiveAsync<Int32>().Wait();
Console.WriteLine(n);
}
});
}
Of course the compiled result of your methods will be completely different from my examples, because compiler smart enough and it can generate code in such way, so some of the lines in your method will be invoked on the context (thread), which calls the method and some of them on the background context. And this is actually why Thread.Sleep(1000); is not recommended in the body of async methods, because this code can be invoked on the thread, which calls this method. Task has equivalent which can replace Thread.Sleep(1000); the equivalent await Task.Delay(1000), which will be invoked on background thread. As you can see await keyword guaranties you that this call will be invoked on the background context and will not block the caller context.
Let's take a look on one more example:
async Task Test1()
{
int a = 0; // Will be called on the called thread.
int b = await this.GetValueAsync(); // Will be called on background thread
int c = GetC(); // Method execution will come back to the called thread again on this line.
int d = await this.GetValueAsync(); // Going again to background thread
}
So we can say that this will be generated code:
Task Test1()
{
int a = 0; // Will be called on the called thread.
vat syncContext = Task.GetCurrentSynchronizationContext(); // This will help us go back to called thread
return Task.Run(() =>
{
// We already on background task, so we safe here to wait tasks
var bTask = this.GetValueAsync();
bTask.Wait();
int b = bTask.Result;
// syncContext helps us to invoke something on main thread
// because 'int c = 1;' probably was expected to be called on
// the caller thread
var cTask = Task.Run(() => return GetC(), syncContext);
cTask.Wait();
int c = cTask.Result;
// This one was with 'await' - calling without syncContext,
// not on the thread, which calls our method.
var dTask = this.GetValueAsync();
dTask.Wait();
int d = dTask.Result;
});
}
Again, this is not the same code which you will get from compiler, but it should just give you some idea how this works. If you really want to take a look on what will be in the produced library, use for example IlSpy to take a look on generated code.
Also I really recommend to read this article Best Practices in Asynchronous Programming
That's exactly what the async keyword means. It takes a method and (usually) converts it to a Task returning method. If the normal method would have the return type of void, the async method will have Task. If the return type would be some other T, the new return type will be Task<T>.
For example, to download an process some data synchronously, you could write something like:
Foo GetFoo()
{
string s = DownloadFoo();
Foo foo = ParseFoo(s);
return foo;
}
The asynchronous version would then look like this:
Task<Foo> GetFoo()
{
string s = await DownloadFoo();
Foo foo = ParseFoo(s);
return foo;
}
Notice that the return type changed from Foo to Task<Foo>, but you're still returning just Foo. And similarly with void-returning methods: since they don't have to contain a return statement, async Task (without any <T>) methods also don't.
The Task object is constructed by the compiler-generated code, so you don't have to do that.
Every variation on the following code that I try doesn't work - whether DoSomething() : void and is called as written, or DoSomething() : Task and is called with TaskEx.RunEx(), some attempt involving .GetAwaiter().GetResult(). Errors seen include: "Start may not be called on a task with null action", "RunSynchronously may not be called on a task unbound to a delegate", and "The task has not yet completed".
class Program
{
static void Main(string[] args) // Starting from a non-async method
{
DoSomething();
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
}
static async void DoSomething()
{
Console.WriteLine("Starting DoSomething ...");
var x = await PrepareAwaitable(1);
Console.WriteLine("::" + x);
var y = await PrepareAwaitable(2);
Console.WriteLine("::" + y);
}
static Task<string> PrepareAwaitable(int id)
{
return new Task<string>(() =>
{
return "Howdy " + id.ToString();
});
}
}
Output:
Starting DoSomething ...
Press any key to quit.
PrepareAwaitable's Task's Action will be more complicated later. When this action completes, however long that takes, I would expect the Task (or other Framework mechanisms) to resume by assigning "Howdy ..." to x, and then later to y. What I REALLY want to do is intercept the awaited objects, process them, and at some later time that I control, resume to the continuation with a result (x and y). But I haven't been getting very far on that big step, so I'm trying to start smaller.
First, read the Task-Based Asynchronous Pattern document. It's under My Documents\Microsoft Visual Studio Async CTP\Documentation. This document describes how to design APIs naturally consumable by await.
Secondly, realize that there are several aspects of the Task class and related APIs that no longer really apply in the new asynchronous world. Task was originally written as the core of TPL. It turned out to be a good fit for asynchronous programming, so Microsoft used it instead of creating a new "Promise" class. But a number of methods are holdovers, used by TPL but not needed for async programming.
To answer the titular question, mixing synchronous and asynchronous code is not quite straightforward with the current async CTP. I've written a library that includes a Task.WaitAndUnwrapException extension method, which makes it easy to call async code from sync code. You may also be interested in my AsyncContext class, which makes the "press any key" prompt unnecessary.
The tasks you returned haven't started yet (i.e., they're "cold" tasks); try replacing the PrepareAwaitable code with the following:
static Task<string> PrepareAwaitable(int x)
{
return Task.Factory.StartNew<string>(() =>
{
return "Howdy " + x.ToString();
});
}
It's really not clear what you're trying to achieve, because there's nothing asynchronous going on. For example, this will compile and run, but I don't know whether it's what you want:
using System;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
DoSomething();
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
}
static async void DoSomething()
{
Console.WriteLine("Starting DoSomething ...");
var x = await PrepareAwaitable(1);
Console.WriteLine("::" + x);
var y = await PrepareAwaitable(2);
Console.WriteLine("::" + y);
}
static async Task<string> PrepareAwaitable(int x)
{
return "Howdy " + x;
}
}
Note that this gives a warning for PrepareAwaitable because there's nothing asynchronous in it; no "await" expressions. The whole program executes synchronously. Another alternative implementation of PrepareAwaitable:
static Task<string> PrepareAwaitable(int x)
{
return TaskEx.Run(() => "Howdy " + x);
}
Is that more like what you were after?
add GetAwaiter().GetResult() after your async task should work. But for eliminating errore like "...not be called on a task with null action", you simply have your Task<IHttpActionResult> to return Ok(true) rather than Ok().
It fixed the GetResult() issue for me !