I googled a lot and for the moment the only async implementation I found (including MSDN site) is the following:
public async void Foo()
{
...
await StreamReader.ReadAsync();
...
}
So in all the cases they use some method which is already async. And this is not what I need.
Let's say that I have a heavy method that does something:
public void DoSomthing()
{
...
}
And there is method where I call this DoSomething:
public void MajorMethod()
{
DoSomething();
}
I want to make DoSomething ayncthonous and call it.
The only solution I see would be the following one:
public Task MajorMethod()
{
return Task.Run(()=>DoSomething());
}
But I read some comments that it's not really the async. So how can I make DoSomething async?
If the MajorMethod has no other things to do other than calling the DoSomething, your code is fine.
But if you need to do other stuff after calling to DoSomething, then mark MajorMethod as async, and use await before Task.Run
public async Task MajorMethod()
{
await Task.Run(()=>DoSomething());
//stuff in here will executed after DoSomething completed
}
Examples from MSDN: Asynchronous programming
or just google c# async
You should be clear about the role async/await play in the Task Asynchronous Pattern. Making an async method does not parform an operation asynchronously just like that. Marking an existing method async will not magically perform everything in there asynchronously. Its main effect is that now you are allowed to use await within the method (I read that it even was discussed if the async keyword was necessary at all; it was added to avoid a breaking change when a local variable in existing methods would be named await).
await also does not provide asynchrony by itself, it provides a way to synchronize to another asnychronous method and yield while the other operation is still running. You can await another async method, but unless somwhere down the chain there is an actual Task running in another thread, the async method might even return synchronously.
In consequence this means that you need an operation that runs asynchronously first (such as a DB query, file access, network communication) and from there you create a chain of async methods that await the previous method.
Now in your case, when you have a computationally intensive method that does not wait for external resources, you can choose to perform the operation asynchronously. Since modern CPUs usually have more than one core at your disposal, you can increase both, performance and application responsiveness like that. The method would not be async, since it does not await anything:
void DoSomething()
{
//...
}
Task DoSomethingAsync() {
return Task.Run(DoSomething);
}
All callers of DoSomethingAsync can now use await to synchronize with this operation running in the background (note the change in return type to Task to allow callers to await):
async Task MajorMethod() {
//...
await DoSomethingAsync();
//...
}
This would allow callers of MajorMethod to synchronize with it. What you can also do is to do stuff in MajorMethod while DoSomethingAsync is running (and still await to allow callers to do even more parallel operations):
async Task MajorMethod() {
//This part will run before DoSomethingAsync
//...
Task doSomethingTask = DoSomethingAsync();
//This part is executed at the same time as DoSomethingAsync
//...
await doSomethingTask; //Here the caller can do more operations while DoSomething is running
//This part will be executed after DoSomethingAsync has finished
//...
}
This form of acquiring a task, doing something and only then awaiting the task has to be done somewhere in the chain, otherwise you have no benefit from the asynchronous operation. Even though this might be an overgeneralization, since synchronization can happen in more subtle ways, for example with a custom synchronization context. But as far as your question is concerned, you should go with: There is an actual task on one end and something that is done after the async call, but before the await on the other end.
Related
I don't quite understand the difference between Task.Wait and await.
I have something similar to the following functions in a ASP.NET WebAPI service:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
Where Get will deadlock.
What could cause this? Why doesn't this cause a problem when I use a blocking wait rather than await Task.Delay?
Wait and await - while similar conceptually - are actually completely different.
Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete. As a general rule, you should use "async all the way down"; that is, don't block on async code. On my blog, I go into the details of how blocking in asynchronous code causes deadlock.
await will asynchronously wait until the task completes. This means the current method is "paused" (its state is captured) and the method returns an incomplete task to its caller. Later, when the await expression completes, the remainder of the method is scheduled as a continuation.
You also mentioned a "cooperative block", by which I assume you mean a task that you're Waiting on may execute on the waiting thread. There are situations where this can happen, but it's an optimization. There are many situations where it can't happen, like if the task is for another scheduler, or if it's already started or if it's a non-code task (such as in your code example: Wait cannot execute the Delay task inline because there's no code for it).
You may find my async / await intro helpful.
Based on what I read from different sources:
An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
To wait for a single task to complete, you can call its Task.Wait method. A call to the Wait method blocks the calling thread until the single class instance has completed execution. The parameterless Wait() method is used to wait unconditionally until a task completes. The task simulates work by calling the Thread.Sleep method to sleep for two seconds.
This article is also a good read.
Some important facts were not given in other answers:
async/await is more complex at CIL level and thus costs memory and CPU time.
Any task can be canceled if the waiting time is unacceptable.
In the case of async/await we do not have a handler for such a task to cancel it or monitoring it.
Using Task is more flexible than async/await.
Any sync functionality can by wrapped by async.
public async Task<ActionResult> DoAsync(long id)
{
return await Task.Run(() => { return DoSync(id); } );
}
async/await generate many problems. We do not know if await statement will be reached without runtime and context debugging. If first await is not reached, everything is blocked. Sometimes even when await seems to be reached, still everything is blocked:
https://github.com/dotnet/runtime/issues/36063
I do not see why I must live with the code duplication for sync and async method or using hacks.
Conclusion: Creating Tasks manually and controlling them is much better. Handler to Task gives more control. We can monitor Tasks and manage them:
https://github.com/lsmolinski/MonitoredQueueBackgroundWorkItem
Sorry for my english.
EDIT: from OP's comment, the goal is
non-blocking background task so that the rest remain responsive
Say I have a function like this:
void OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
ProcessAsynchronously(_latestImageBytes);
//some more code here
}
In the point commented, I want to introduce a call to an asynchronous function.
Now, I can not modify OnFrameSampleAcquired (meaning I can not make it "async").
How can I do this?
I am thinking
async void ProcessAsynchronously(byte[] image)
{
await Process1(image);
await Process2(image);
// ...
}
or async Task ProcessAsynchronously(byte[] image)
where ProcessX are also declared as async
Is this a good approach?
Thanks for any insight, since my practical experience with asynchronous processing is very few.
EDITED included all suggestions from the comments and added some background.
Background & insights
Converting one function to async won't be enough to make the whole process non-blocking. To achieve what you want, the whole processing path (call stack) should be converted to non-blocking. One blocking method on your call stack is enough to render the whole process blocking. Non-blocking does not necessarily mean async, as some of the examples below will show.
There are two steps involved in converting a method into async:
Change the signature to return Task. This will allow your callers track status and outcome of your method.
Add async keyword to the signature. This will allow await-ing other async methods in the body of your method.
CPU-bound vs IO-bound tasks
Note that even when you await for a method, it doesn't necessarily mean that you immediately release the thread back to your caller. The method being await-ed will release the thread back to you only as soon as it in turn begins await-ing for an IO-bound operation. Your thread will still block while the await-ed method performs CPU-bound operations before the first time it is await-ing for an IO-bound operation.
For example:
async Task MyAsyncMethod()
{
Thread.Sleep(5000); // equivalent to CPU-bound operations
}
await MyAsyncMethod(); // will block for 5 seconds
On the other hand,
async Task MyAsyncMethod()
{
await Task.Delay(5000); // equivalent to IO-bound operations
}
await MyAsyncMethod(); // will return immediately
And the workaround if you have CPU-bound tasks but still don't want to block the caller thread:
async Task MyAsyncMethod()
{
await Task.Yield(); // this does the magic
Thread.Sleep(5000); // equivalent to CPU-bound operations
}
await MyAsyncMethod(); // will return immediately thanks to Task.Yield()
What to do in your case
Since I'm not sure why you cannot change OnFrameSampleAcquired signature to async, I will suggest several different options.
Option 1
The simplest and the truly asynchronous approach would be this:
async Task OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
await ProcessAsynchronously(_latestImageBytes);
//some more code here -- provided it is either async or non-blocking!
}
async Task ProcessAsynchronously(byte[] image)
{
await Process1(image);
await Process2(image);
// ...
}
If all of the methods on your processing path look like these, you have a properly implemented non-blocking background job.
Option 2
If you're absolutely unable to change the signature OnFrameSampleAcquired, there is a workaround. You can instead invoke the rest of the processing asynchronously, as suggested by #Fildor:
public void OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
ProcessAsynchronously(_latestImageBytes).ContinueWith(task => {
// this runs on a different thread after ProcessAsynchronously is completed
// some more code here
});
// return without blocking
}
Here you win on both sides: first, you don't have to change the signature of OnFrameSampleAcquired; second, OnFrameSampleAcquired is now a non-blocking method.
Option 3
If you cannot change your signature because you must implement an interface like this:
public interface ISomeInterface
{
void OnFrameSampleAcquired(VideoCaptureSample sample);
// ... other members
}
then you can add the async keyword to your method and still comply with the interface:
async void OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
await ProcessAsynchronously(_latestImageBytes);
//some more code here
}
ISomeInterface x; // initialized elsewhere
x.OnFrameSampleAcquired(/*....*/); // the same as await, but no error handling
The drawback of this option is that the callers cannot track nor the status of the task (still running or completed?), neither its outcome (completed or threw exception?). You will probably have to wrap the entire body of OnFrameSampleAcquired in a try/catch, and write an exception to log.
Option 4
Technically, you can also invoke an async ProcessAsynchronously from a non-async OnFrameSampleAcquired using Wait on a Task, but it won't achieve your goal of having a non-blocking background task. The Wait() will block the thread until the async processing is done:
void OnFrameSampleAcquired(VideoCaptureSample sample)
{
//Some code here
//Here I want to introduce an Asynchrnous process
ProcessAsynchronously(_latestImageBytes).Wait();
//some more code here
}
The Task does not maintain a wait handle for performance reasons, and only lazily constructs one if the code were to ask one of it.
How then does a Task know it has been completed?
One would argue that the implementer sets the result on the TaskCompletionSource in their implementation but that would explain only the modern implementations and re-writes such as System.IO.FileStream.Begin/EndReadTask.
I followed the Task.IsComplete property; almost in every instance, an internal bitwise flag field (m_stateFlags) is set by the TrySetResult / TrySetException methods to indicate the status of the task.
But that does not cover all cases.
What about a method such as this?
public async Task FooAsync()
{
await Task.Run(() => { });
}
How then does a Task know it has been completed?
As I describe on my blog (overview, more detail), there are two kinds of tasks: Delegate Tasks (which execute code) and Promise Tasks (which represent an event).
Delegate Tasks complete themselves when their delegate completes.
Promise Tasks are completed from an external signal, using TaskCompletionSource<T> (or equivalent methods that are internal to the BCL).
I am answering my own question because I have suddenly remembered that I know the answer to it.
When using the C# Language Support Features
It's the state machine.
If the implementer of the asynchronous method used the C# language support such as the async keyword in the method declaration and the await keyword inside the method body to await an operation intrinsic to the task, then to the extent of the task he is implementing, the state machine signals task completion by setting the result of the task.
For e.g. if his implementation was as such:
// client code
public async void TopLevelMethod()
{
await MyMethodAsync();
}
// library code -- his implementation
public async Task MyMethodAsync()
{
await AnotherOperationAsync();
}
Then the completion of MyMethodAsync will be entrusted to the compiler generated state machine.
Of course, the signaling of completion of AnotherOperationAsync will also be taken care of by the compiler generated state machine, but that is not the point here.
Recall the states inside the MoveNext method indicate the task completion states and in the block inside of MoveNext that invokes the continuation callback, it also calls SetResult on the AsyncXXXMethodBuilder.
When not using the C# Language Support Features
If, however, the implementer of the asynchronous method did not make use of the C# language features, then it is the duty of the implementer to signal the completion of the task by setting the relevant result, exception or cancelled properties on the TaskCompletionSource object.
For e.g.
public Task MyMethodAsync()
{
var tcs = new TaskCompletionSource<object>();
try
{
AnotherOperation();
tcs.SetResult();
}
catch(Exception ex)
{
tcs.SetException(ex);
}
return tcs.Task;
}
If the implementer did not use TPL support or invoked another operation asynchronously using the older .NET API, then too, it is the implementer's responsibility to signal task completion by explicitly setting the status of the task through one of the Try/SetResult/Exception etc. methods.
For e.g.
public Task MyMethodAsync()
{
var tcs = new TaskCompletionSource...
var autoReseEvent = ...
ThreadPool.QueueUserWorkItem(new WaitCallback(() =>
{
/* Work */
Thread.SpinWait(1000);
tcs.SetResult(...);
autoResetEvent.Set();
};)...;
return tcs.Task;
}
An Ill-Advised Case
The best way to await a task is, of course, to use the await keyword. If, however, when implementing an asynchronous API, the implementer does this:
public Task MyMethodAsync()
{
return Task.Run(...);
}
That would leave the consumer of his API with a sour mouth, I suppose?
Task.Run should only ever be used in a fire and forget scenario where you do not care about the point in time when the task will be completed.
The one exception to this is if you awaited the task returned by the call to Task.Run using the await keyword, like the code snippet shown below, in which case, you would be using the language support as described in the first section.
public async Task MyMethodAsync()
{
await Task.Run(...);
}
Let's suppose that I Have two methods, like this...
public void MyMethod()
{
// do some stuff
}
public Task MyMethodAsync()
{
//run MyMethod asynchronously
}
What is the best form to execute it in async way?
Like this
public Task MyMethodAsync()
{
return Task.Run(() => MyMethod());
}
or like this?
public async Task MyMethodAsync()
{
await Task.Run(() => MyMethod());
}
You should read Stephen Cleary's tutorial on when -- and when not -- to use Task.Run.
Short answer: don't use Task.Run to create a fake async method. If your code isn't truly async, then let the caller decide if it should use a thread (or whatever) to call your code.
In the case of your first method, you may as well just have a task on a separate thread. It's not really async because you aren't clearly waiting for the thread to end to start a new process. If you called this it would continue before the task was complete.
public Task MyMethodAsync()
{
return Task.Run(() => MyMethod());
}
Looking at the second version. You are waiting for the task to complete so that you can do something after without holding up the current thread.
public async Task MyMethodAsync()
{
await Task.Run(() => MyMethod());
DoMoreWork();
//Do something following the completion of the task
//without binding up the calling thread, but actually complete it on that thread.
}
It's better to go the other way around. Build the inner task as async, and then let all the callers who can't use the async method use the async one internally and wait on it.
public void MyMethod()
{
MyMethodAsync().Wait();
}
public async Task MyMethodAsync()
{
// do some stuff
}
Both of your methods aren't truly making anything async. Async isn't about running something in the background, that's the realm of the Task library (or parallel extensions, or threading, etc). Async is about being able to re-use a single thread for multiple things when it has nothing better to do -- which makes thing more scalable. Making a pseudo-async method is just hiding the fact that you are using a NEW thread instead of reusing the same thread, which makes the system LESS scalable.
In order to do that, true async processes need to be written that way from the inside out. Everything (or at least the parts that are time consuming) need to rely on async methods that do that. For example, making a SOAP call where the thread is going to basically just sit idle while waiting for the call to return, or a database call, or file I/O. Async allows that thread to go do something else useful instead of just sitting idle.
I don't quite understand the difference between Task.Wait and await.
I have something similar to the following functions in a ASP.NET WebAPI service:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
Where Get will deadlock.
What could cause this? Why doesn't this cause a problem when I use a blocking wait rather than await Task.Delay?
Wait and await - while similar conceptually - are actually completely different.
Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete. As a general rule, you should use "async all the way down"; that is, don't block on async code. On my blog, I go into the details of how blocking in asynchronous code causes deadlock.
await will asynchronously wait until the task completes. This means the current method is "paused" (its state is captured) and the method returns an incomplete task to its caller. Later, when the await expression completes, the remainder of the method is scheduled as a continuation.
You also mentioned a "cooperative block", by which I assume you mean a task that you're Waiting on may execute on the waiting thread. There are situations where this can happen, but it's an optimization. There are many situations where it can't happen, like if the task is for another scheduler, or if it's already started or if it's a non-code task (such as in your code example: Wait cannot execute the Delay task inline because there's no code for it).
You may find my async / await intro helpful.
Based on what I read from different sources:
An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
To wait for a single task to complete, you can call its Task.Wait method. A call to the Wait method blocks the calling thread until the single class instance has completed execution. The parameterless Wait() method is used to wait unconditionally until a task completes. The task simulates work by calling the Thread.Sleep method to sleep for two seconds.
This article is also a good read.
Some important facts were not given in other answers:
async/await is more complex at CIL level and thus costs memory and CPU time.
Any task can be canceled if the waiting time is unacceptable.
In the case of async/await we do not have a handler for such a task to cancel it or monitoring it.
Using Task is more flexible than async/await.
Any sync functionality can by wrapped by async.
public async Task<ActionResult> DoAsync(long id)
{
return await Task.Run(() => { return DoSync(id); } );
}
async/await generate many problems. We do not know if await statement will be reached without runtime and context debugging. If first await is not reached, everything is blocked. Sometimes even when await seems to be reached, still everything is blocked:
https://github.com/dotnet/runtime/issues/36063
I do not see why I must live with the code duplication for sync and async method or using hacks.
Conclusion: Creating Tasks manually and controlling them is much better. Handler to Task gives more control. We can monitor Tasks and manage them:
https://github.com/lsmolinski/MonitoredQueueBackgroundWorkItem
Sorry for my english.