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.
Related
In contrast to Task.Wait() or Task.Result, await’ing a Task in C# 5 prevents the thread which executes the wait from lying fallow. Instead, the method using the await keyword needs to be async so that the call of await just makes the method to return a new task which represents the execution of the async method.
But when the await’ed Task completes before the async method has received CPU time again, the await recognizes the Task as finished and thus the async method will return the Task object only at a later time. In some cases this would be later than acceptable because it probably is a common mistake that a developer assumes the await’ing always defers the subsequent statements in his async method.
The mistaken async method’s structure could look like the following:
async Task doSthAsync()
{
var a = await getSthAsync();
// perform a long operation
}
Then sometimes doSthAsync() will return the Task only after a long time.
I know it should rather be written like this:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Run(() =>
{
// perform a long operation
};
}
... or that:
async Task doSthAsync()
{
var a = await getSthAsync();
await Task.Yield();
// perform a long operation
}
But I do not find the last two patterns pretty and want to prevent the mistake to occur. I am developing a framework which provides getSthAsync and the first structure shall be common. So getSthAsync should return an Awaitable which always yields like the YieldAwaitable returned by Task.Yield() does.
Unfortunately most features provided by the Task Parallel Library like Task.WhenAll(IEnumerable<Task> tasks) only operate on Tasks so the result of getSthAsync should be a Task.
So is it possible to return a Task which always yields?
First of all, the consumer of an async method shouldn't assume it will "yield" as that's nothing to do with it being async. If the consumer needs to make sure there's an offload to another thread they should use Task.Run to enforce that.
Second of all, I don't see how using Task.Run, or Task.Yield is problematic as it's used inside an async method which returns a Task and not a YieldAwaitable.
If you want to create a Task that behaves like YieldAwaitable you can just use Task.Yield inside an async method:
async Task Yield()
{
await Task.Yield();
}
Edit:
As was mentioned in the comments, this has a race condition where it may not always yield. This race condition is inherent with how Task and TaskAwaiter are implemented. To avoid that you can create your own Task and TaskAwaiter:
public class YieldTask : Task
{
public YieldTask() : base(() => {})
{
Start(TaskScheduler.Default);
}
public new TaskAwaiterWrapper GetAwaiter() => new TaskAwaiterWrapper(base.GetAwaiter());
}
public struct TaskAwaiterWrapper : INotifyCompletion
{
private TaskAwaiter _taskAwaiter;
public TaskAwaiterWrapper(TaskAwaiter taskAwaiter)
{
_taskAwaiter = taskAwaiter;
}
public bool IsCompleted => false;
public void OnCompleted(Action continuation) => _taskAwaiter.OnCompleted(continuation);
public void GetResult() => _taskAwaiter.GetResult();
}
This will create a task that always yields because IsCompleted always returns false. It can be used like this:
public static readonly YieldTask YieldTask = new YieldTask();
private static async Task MainAsync()
{
await YieldTask;
// something
}
Note: I highly discourage anyone from actually doing this kind of thing.
Here is a polished version of i3arnon's YieldTask:
public class YieldTask : Task
{
public YieldTask() : base(() => { },
TaskCreationOptions.RunContinuationsAsynchronously)
=> RunSynchronously();
public new YieldAwaitable.YieldAwaiter GetAwaiter()
=> default;
public new YieldAwaitable ConfigureAwait(bool continueOnCapturedContext)
{
if (!continueOnCapturedContext) throw new NotSupportedException();
return default;
}
}
The YieldTask is immediately completed upon creation, but its awaiter says otherwise. The GetAwaiter().IsCompleted always returns false. This mischief makes the await operator to trigger the desirable asynchronous switch, every time it awaits this task. Actually creating multiple YieldTask instances is redundant. A singleton would work just as well.
There is a problem with this approach though. The underlying methods of the Task class are not virtual, and hiding them with the new modifier means that polymorphism doesn't work. If you store a YieldTask instance to a Task variable, you'll get the default task behavior. This is a considerable drawback for my use case, but I can't see any solution around it.
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.
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.
I'm having a hard time understanding async and the corresponding behavior. This is a model of the program I'm trying to write, and a repro of the problem I'm having:
namespace AsyncTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("starting....");
MyClass myClass = new MyClass();
myClass.DoSomeWork();
Console.WriteLine("ending....");
Console.ReadLine();
}
}
class MyClass
{
public bool DoSomeWork()
{
return GetTrue().Result;
}
Task<bool> GetTrue()
{
return new Task<bool>(() => true);
}
}
}
When I make the GetTrue().Result call, it never returns. My Task<bool> GetTrue() method is a dummy method for repro purposes, but I'm not quite sure why it never comes back. But it returns if I have this:
namespace AsyncTesting
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("starting....");
MyClass myClass = new MyClass();
myClass.DoSomeWork();
Console.WriteLine("ending....");
Console.ReadLine();
}
}
class MyClass
{
public async void DoSomeWork()
{
await GetTrue();
}
Task<bool> GetTrue()
{
return new Task<bool>(() => true);
}
}
}
The problem is, with my repro I want the initial behavior. I don't want async void for the calling method. I want to be able to return bool from my calling "normal" method. How can I achieve this? How can I get the first example to run and actually return the bool from DoSomeWork()?
Thank you in advance.
EDIT: Thank you for the answers. I think what the problem is, is that my GetTrue() method isn't a true repro. In my method, I'm not generating the actual Task<bool> object. It's really a call to Task.Factory.FromAsync<bool>() that is creating the Task<bool> object. And it's that task that I don't know how to "start". Any other ideas? Thanks!
You're probably looking for:
Task<bool> GetTrue()
{
return Task.FromResult(true);
}
instead of:
Task<bool> GetTrue()
{
return new Task<bool>(() => true);
}
In the latter case, you don't even start the task you create. You'd need to start it with Task.Run or Task.RunSynchronously. Usually you don't create tasks directly via new Task(). Check Stephen Toub's "Task.Factory.StartNew" vs "new Task(...).Start" and "Task.Run vs Task.Factory.StartNew".
Depending on what you're trying to achieve, you might be tempted to do this:
Task<bool> GetTrue()
{
return Task.Run(() => true);
}
However, usually this turns to be a known-anti-pattern, check "Should I expose asynchronous wrappers for synchronous methods?".
Updated to address the comments:
... the context is a WCF service. The Task.Factory.FromAsync()
call is wrapping the Begin...() and End...() functions that the
service has pushed to the consumer. But I see no way to actually start
the task and it just hangs.
... it is the client-side making the WCF call. The client-side app is a
Windows Phone 8 application.
You're experiencing a deadlock on the UI thread, because you're blocking on the result of a pending task (with task.Result). The task itself cannot be completed, because the await continuation is posted asynchronously to the dispatcher loop of the UI thread of your WP8 app, which is now blocked. Stephen Cleary explains this in great details in his blog. To avoid this, you should embrace "async all the way down" programming model. It practically means that you should make your UI event and command handlers async as well, and do var result = await task, rather than var result = task.Result in there.
You need to start a task before it does anything.. calling Run will do that for you:
Task<bool> GetTrue()
{
return Task.Run(() => true);
}
This gives the output you expect. Result is a blocking call. If your Task instance never starts.. Result can never return.
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