How to safely call an async method in C# without await
If you want to get the exception "asynchronously", you could do:
MyAsyncMethod().
ContinueWith(t => Console.WriteLine(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
This will allow you to deal with an exception on a thread other than the "main" thread. This means you don't have to "wait" for the call to MyAsyncMethod()
from the thread that calls MyAsyncMethod
; but, still allows you to do something with an exception--but only if an exception occurs.
Update:
technically, you could do something similar with await
:
try
{
await MyAsyncMethod().ConfigureAwait(false);
}
catch (Exception ex)
{
Trace.WriteLine(ex);
}
...which would be useful if you needed to specifically use try
/catch
(or using
) but I find the ContinueWith
to be a little more explicit because you have to know what ConfigureAwait(false)
means.
C# How to start an async method without await its complete?
If you truly just want to fire and forget. Simply don't call use await.
// It is a good idea to add CancellationTokens
var asyncProcedure = SomeHTTPAction(cancellationToken).ConfigureAwait(false);
// Or If not simply do:
var asyncProcedure = SomeHTTPAction().ConfigureAwait(false);
If you want to use the result output later its gets trickier. But if it is truly fire and forget the above should work
A Cancellation token allows interrupts and canceling procedures. If you are using Cancellation token you will need to use it everywhere from the retrieval straight through to the calling method (Turtles all the way down).
I used ConfigureAwait(false)
to prevent deadlocks. Here for more information
Use async without await with a function that holds another function that returns void
It's important to distinguish asynchronous from parallel.
Asynchronous means not blocking the current thread while you're waiting for something to happen. This lets the current thread go do something else while waiting.
Parallel means doing more than one thing at the same time. This requires separate threads for each task.
You cannot call FunctionReturningVoid
asynchronously because it is not an asynchronous method. In your example, Console.WriteLine()
is written in a way that will block the thread until it completes. You can't change that. But I understand that's just your example for this question. If your actual method is doing some kind of I/O operation, like a network request or writing a file, you could rewrite it to use asynchronous methods. But if it's doing CPU-heavy work, or you just can't rewrite it, then you're stuck with it being synchronous - it will block the current thread while it runs.
However, you can run FunctionReturningVoid
in parallel (on another thread) and wait for it asynchronously (so it doesn't block the current thread). This would be wise if this is a desktop application - you don't want to lock up your UI while it runs.
To do that, you can use Task.Run
, which will start running code on another thread and return a Task
that you can use to know when it completes. That means your WrapperFunction
would look like this:
public Task WrapperFunction()
{
return Task.Run(() => this.FunctionReturningVoid("aParameter"));
}
Side point: Notice I removed the async
keyword. It's not necessary since you can just pass the Task
to the calling method. There is more information about this here.
Microsoft has some well-written articles about Asynchronous programming with async and await that are worth the read.
call async method without await #2
If you call an async method from a single threaded execution context, such as a UI thread, and wait for the result synchronously, there is a high probability for deadlock. In your example, that probability is 100%
Think about it. What happens when you call
ValidateRequestAsync(userName, password).Result
You call the method ValidateRequestAsync. In there you call ReadAsStringAsync. The result is that a task will be returned to the UI thread, with a continuation scheduled to continue executing on the UI thread when it becomes available. But of course, it will never become available, because it is waiting (blocked) for the task to finish. But the task can't finish, because it is waiting for the UI thread to become available. Deadlock.
There are ways to prevent this deadlock, but they are all a Bad Idea. Just for completeness sake, the following might work:
Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;
This is a bad idea, because you still block your UI thread waiting and doing nothing useful.
So what is the solution then? Go async all the way. The original caller on the UI thread is probably some event handler, so make sure that is async.
Are awaits in async method called without await still asynchronous?
Async methods always start running synchronously. The magic happens at await
, but only when await
is given a Task
that has not completed.
In your example, this is what will happen when you call Run()
:
- Jump to
DoStuffAsync()
- Jump to
PerformCalc()
- Jump to
DoLongTaskAsync()
- If
DoLongTaskAsync()
is a truly asynchronous operation and returns an incompleteTask
, thenawait
does its job andDoStuffAsync()
returns an incompleteTask
toRun()
. - Since the task is not awaited,
Run()
completes. - When
DoLongTaskAsync()
completes,DoStuffAsync()
resumes, and jumps toPerformAnotherCalc()
.
All of that can happen on the same thread.
So to answer your questions:
- Yes. If it is an
async
method, it might end up going out and doing things on other threads. But it will start synchronously on the same thread. DoLongTaskAsync()
will be called asynchronously, butPerformAnotherCalc()
will not be called beforeDoLongTaskAsync()
finishes, because you usedawait
.- Yes. This is how
await
works. It will return an incompleteTask
(that is, only ifDoLongTaskAsync()
is truly asynchronous and returns an incompleteTask
). Then onceDoLongTaskAsync()
finishes, execution ofDoStuffAsync()
resumes where it left off.
C#: calling [async] method without [await] will not catch its thrown exception?
Within an async
method, any exceptions are caught by the runtime and placed on the returned Task
. If your code ignores the Task
returned by an async
method, then it will not observe those exceptions. Most tasks should be await
ed at some point to observe their results (including exceptions).
The easiest solution is to make your Main
asynchronous:
public static async Task Main(string[] args)
{
try
{
await ProcessAsync(null);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
C# Async Task Method Without Await or Return
public Task DoSomething()
{
return Task.CompletedTask;
}
No need for the async
.
If you're using an older version of .NET, use this:
public Task DoSomething()
{
return Task.FromResult(0);
}
If you find you need to return a result but you still dont need to await
anything, try;
public Task<Result> DoSomething()
{
return Task.FromResult(new Result())
}
or, if you really want to use async (not recommended);
public async Task<Result> DoSomething()
{
return new Result();
}
Related Topics
How Using Try Catch for Exception Handling Is Best Practice
Keeping ASP.NET Session Open/Alive
How to Get the Unix Timestamp in C#
Cannot Delete Directory with Directory.Delete(Path, True)
Authenticate and Request a User's Timeline with Twitter API 1.1 Oauth
Getting the Size of a Field in Bytes with C#
Binding a Button's Visibility to a Bool Value in Viewmodel
When to Use Ref and When It Is Not Necessary in C#
C# - Multiple Generic Types in One List
Making a Simple Ajax Call to Controller in ASP.NET MVC
How to Stop C# Console Applications from Closing Automatically
Can Anonymous Class Implement Interface
How to Calculate Distance Similarity Measure of Given 2 Strings
Differencebetween a Shared Project and a Class Library in Visual Studio 2015
Error: "Cannot Modify the Return Value" C#
Command (.4Gl) Executed with Ssh.Net Sshclient.Runcommand Fails with "No Such File or Directory"
Selectsinglenode Returns Null When Tag Contains Xmlnamespace