Using async without await - c#

I'd like to make a function async, so I simply add async like this:
public async static void something(){
}
You can see that its return-type is void. I just want this function to be called asynchronously without blocking, since return is void so no await is needed.
But Visual Studio 2012 just cannot compile this, it says that I miss await?
Could you please advise a sample that makes a function async without using await.

I think that maybe you misunderstand what async does. The warning is exactly right: if you mark your method async but don't use await anywhere, then your method won't be asynchronous. If you call it, all the code inside the method will execute synchronously.
Also, you should try to avoid using async void methods, they make handling exceptions difficult.

Change to
public async Task something(){
return await Task.Factory.StartNew(() => {
//TODO:
}
}
You do not have to wait for the Task returned ;)
so alternatively You can just use a task and remove both async and await and then you get:
public Task something(){
return Task.Factory.StartNew(() => {
//TODO:
}
}
Task is implict void, if you do not use the generic return type argument

Related

awaiting inside an awaitable function in .net

I have a function that returns a Task
class Sample
{
TaskCompletionSource<int> _tcs;
..
public Task<int> DoIt(){
StartDoingStuff();
return _tcs.Task;
}
..
private void FinshedStuffCallBack(){
_tsc.SetResult(42);
}
}
Caller goes
var sample = new Sample();
var result = await Sample.DoIt();
works fine
Now I need to do something in addition in DoIt, this is itself awaitable
I naively tried
public async Task<int> DoIt(){
await DoOtherAsyncStuff();
StartDoingStuff();
return _tcs.Task;
}
but this is not allowed
CS4016 Since this is an async method, the return expression must be of
type 'int' rather than 'Task'
OK I get what its trying to say, but thats not my intention, I dont have the return value yet, it comes once StartDoingStuff triggers the callback.
Not sure what to try next.
Most likely you just need (note the await on the last line):
public async Task<int> DoIt()
{
await DoOtherAsyncStuff();
StartDoingStuff();
return await _tcs.Task;
}
await is needed on the last line because an async function returning Task<int> needs to return int, while _tcs.Task is a Task<int>. Using await will wait for the Task's completion and return the int which is what we need.
However, depending on your complete code you may want something else. For example if you're doing more complicated things with TaskCompletionSource you may need to remove async for this definition and do something like
public Task<int> DoIt()
{
return DoOtherAsyncStuff().ContinueWith(_ =>
{
StartDoingStuff();
return _tcs.Task;
}, TaskCompletionOptions.ExecuteSynchronously);
}
In general it's best not to mess with TaskCompletionSource unless you're doing something more advanced, for example providing an async abstraction of something synchronous/callback based. Hence a complete code example may change my answer (for example what's the body of StartDoingStuff + DoOtherAsyncStuff?).

Call async method from property setter

I have a couple of places where I do this, but it's not feasible/practical to rework the code. However it seems that the method can just be called "normally", e.g.:-
set
{
...
DoSomethingAsync();
}
A squiggle appears in the VS editor under this line, with this tooltip warning:-
Because this call is not awaited, execution of the current method continues before the call is completed.
Without the async/await keywords I kind of expected that the method would end up being called synchronously. What am I not getting here?
If I change the line to the following then the squiggle/warning disappears:-
DoSomethingAsync().Wait();
Presumably this turns it into a blocking call?
And purely out of curiosity, what would be the implications of doing the following:-
Task.Run(() => DoSomethingAsync());
Without the async/await keywords I kind of expected that the method would end up being called synchronously. What am I not getting here?
Your assumption is wrong: an async method is always called asynchronously. Unless you Wait() it, it will not wait until the async method is done. Wait() will indeed block the call to your async method. Even if you do Task.Run, it will run asynchonously (twice, since it async method runs asynchronously within your Task.Run).
Properties can't be called asynchronously, so a Get method would do the trick here. That way you can make your code asynchronous all the way.
Call Async method within a property setter (MVVM usage)
Create the method
public class AsyncRunner
{
public static void Run(Task task, Action<Task> onError = null)
{
if (onError == null)
{
task.ContinueWith((task1, o) => { }, TaskContinuationOptions.OnlyOnFaulted);
}
else
{
task.ContinueWith(onError, TaskContinuationOptions.OnlyOnFaulted);
}
}
}
Call it within a setter property
private NavigationMenuItem _selectedMenuItem;
public NavigationMenuItem SelectedMenuItem
{
get { return _selectedMenuItem; }
set
{
_selectedMenuItem = val;
AsyncRunner.Run(YourAsyncMethod(_selectedMenuItem));
}
}
This is the async method that needs to be run...
private async Task YourAsyncMethod(NavigationMenuItem newNavigationMenu)
{
//call async tasks...
}
If you look at the definition of DoSomethingAsync() it will be something like this
public async Task<T> DoSomethingAsync()
public Task<T> DoSomethingAsync()
Either way, it will return a Task which has (probably) only just started.
You can either call .Wait() on the task, or not.
If not, you are leaving that Task to run in the background.
That's probably not the programmer's intention - hence the warning.

Find awaitable methods in code with Visual Studio

I have a problem where async methods are being called in the code without await in front of it. Is there a way to find all the awaitable methods that do not have await?
Edit - I'm particularly concerned with the scenario where multiple async methods are being called (ignoring the return values), but only one has await which is enough to make Visual Studio not warn about it.
If you use ReSharper and turn solution-wide analysis on, your methods that are returning tasks that are not being awaited will have the Task portion of the method signature grayed out due to "return value is not used." The caveat here is that this will only find methods that are not being awaited anywhere in your solution; the warning will go away after one or more usages are updated to await (or use/reference the Task).
If you're looking for async methods that don't contain an await call (meaning they don't need to be labeled async), ReSharper will tell you about that too in a similar fashion.
class AClass
{
public async void Foo() //async grayed out
{
DoSomethingAsync();
Console.WriteLine("Done");
}
public Task<bool> DoSomethingAsync() //Task<bool> grayed out
{
return Task.Run(() => true);
}
}
Note this will not work if you have code that looks like this:
class AClass
{
public async void Foo()
{
bool b = DoSomethingAsync().Result;
Console.WriteLine("Done");
}
public Task<bool> DoSomethingAsync()
{
return Task.Run(() => true);
}
}
The async keyword, if present, will still be flagged, which means you can probably figure out pretty quickly a Task is not being awaited, but if the calling method is not marked async you are out of luck.

Where is the return statement in async/await

I have probably worked myself into a rather immature confusion. Please refer the code below (console app)
namespace Tasks101
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
var x = p.Blah();
}
private async Task Blah()
{
await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
}
private async void ReturnsVoid()
{
await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
}
private void Nothing()
{
}
}
}
My question is that in Blah() method I don't have any explicit return statement yet when this executes
var x = p.Blah();
the type of x is Task. Again I have no return statement in ReturnsVoid method but that compiles too.
So the questions are
What is returning a Task from the Blah method without my having a return statement there and why is that same thing not returning anything from ReturnsVoid method.
How do I control what gets returned from the Blah method? What if I had two await statements there one after the other?
The async keyword transforms the method and constructs the returned Task instance. There is nothing returned from the async void method because it returns void; this lack of a Task is one reason why you should avoid async void. async void is not a natural asynchronous method signature; it is only supported so that event handlers may be async.
If you want to return a value, then you should have the method return a Task<T>, e.g., Task<int> BlahAsync(), and then you can just return the value directly, e.g., return 13; The number of awaits in the method has nothing to do with it. When the method executes the actual return (e.g., return 13), the async keyword interprets that as completing the Task<int> that was already constructed.
I have an async intro on my blog that you may find helpful.
The compiler is generating a Task for you that represents the entire asynchronous operation.
You have 3 options for async methods:
async void - This should be avoided in all cases other than event handlers
async Task - Here you have no control of the returned task, and it will be completed when the whole operation has ended (or when an exception is thrown) no matter how many awaits you have in it.
async Task<T> - This allows to actually return a value but behaves just the same as async Task.

create a custom async function (that is not calling another .net async method)

seems that all async examples end up calling a .net async method,
is it possible to create a custom async method that is not calling a .net async method ?
this is where I got so far:
[Test]
public void Test()
{
TestAsync();
}
public async void TestAsync()
{
await DoStuffAsync(1);
Task.Run(() => DoStuffAsync(73));
await Task.WhenAll(DoStuffAsync(2), DoStuffAsync(3));
}
public async Task DoStuffAsync(int n)
{
Thread.Sleep(1000);
Console.WriteLine("done stuff " + n);
}
the only problem with this is that VS says that async keyword in DoStuffAsync is useless (cuz there's no await), but I don't need await, I just need the possibility to await this method
The primary purpose of the async keyword is to enable the await keyword. An async method without an await doesn't make much sense, hence the compiler warning.
You can implement a Task-returning method without async, as such:
public Task DoStuffAsync(int n)
{
return Task.Delay(1000);
}
If you want to create your own Tasks from scratch, use Task.Run or TaskCompletionSource<T> (or one of its shortcuts such as Task.FromResult or TaskFactory.FromAsync).
P.S. You generally want to avoid async void; use async Task instead.
public async void TestAsync()
{
await DoStuffAsync(1);
await DoStuffAsync(73);
await Task.WhenAll(DoStuffAsync(2), DoStuffAsync(3));
}
public async Task DoStuffAsync(int n)
{
await Task.Delay(1000);
Console.WriteLine("done stuff " + n);
}

Categories

Resources