So I read on async/await and somewhere, someplace I read that if you don't await an async method you basically lose it. It fires and forgets and goes into the AEeher and if it throws an exception - you will never know.
This was the example the author used:
static async void OnButtonClick()
{
yolo();
string imageUrl = null;
try
{
DownloadAndBlur(imageUrl);
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex}");
}
Console.WriteLine("Done!");
}
static async Task DownloadAndBlur(string url)
{
if (url == null)
{
throw new ArgumentNullException(nameof(url));
}
}
Indeed, if I call the OnButtonClick() method from my code no exception gets thrown, or rather, nothing about an exception is printed on the console. While if I await the DownloadAndBlur method - an exception is written to the console.
So I tried to replicate the behaviour and wrote this:
static async void Execute()
{
Console.WriteLine(1);
yolo();
Console.WriteLine(2);
}
static Task yolo()
{
throw new Exception();
}
But an exception is thrown and my debugging session catches it. So what is different, because I think they are the same.
The Execute method is not fire-and-forget. It is async void.
static async void Execute()
{
YoloAsync();
}
Exceptions in async void methods are thrown in the current SynchronizationContext (or in the ThreadPool if the SynchronizationContext.Current is null), which normally results to the crashing of the process (source code).
Next, the YoloAsync method is not marked with the async modifier.
static Task YoloAsync()
{
throw new Exception();
}
Semantically it is an asynchronous method since it returns a Task, but the task is not generated from an async-state-machine. So the code inside the YoloAsync method is executed synchronously like any other method, and unlike the async-state-machine-generated methods that propagate their exceptions through the Task they return.
Maxim 26. "Fire and Forget" is fine, provided you never actually forget.
Getting a Exception in Multitasking is always difficulty.
If you are doing Mutlthreading, it is actually trivially easy to loose all exceptions by default. The thread itself swallows all Exceptions. This is the worst case that has to be handeled.
As a result, Multitasking approaches always catch all exceptions, then expose them in the Result. Task has a property for that. So Does RunWorkerCompletedEventArgs.
One job of the continuation code, is to check for and re-raise any Exceptions. It is something Task has to do for Multithreading support, even if it does not nessearily make sense with mere Multitasking.
Related
In constructor I want to call one method type :
private async Task OnLoadPrometDanKorisnikDatum
and I want to wait that method while its finish, and I have more method(3) like this and I want to call this 3 methods in background thread and don't wait him to finish, just want to wait first method. And I want to them executing parallel.
I have methods async Task,and in constructor of view model I call like this
OnLoadPrometDanKorisnikDatum(KorisnikID, PomocnaDnDDatnaDat,
DatumVrednost).Wait();
OnLoadPrometNedelja(KorisnikID, PomocnaDnDDatnaDatNedelja).Wait();
if I don't place .Wait() on the end, program doesn't work. I see in debug mode they run asynchronly, but time spent tell me that they sub(one method time + second method time + ....).
Can someone help me, this is for me very stuf...
Answer
The best way to handle your scenario is to use async void.
I recommend first reading the Explanation section below to fully understand the best practices around async void.
public MyConstructor()
{
ExecuteAsyncMethods();
}
async void ExecuteAsyncMethods()
{
try
{
await OnLoadPrometDanKorisnikDatum(KorisnikID, PomocnaDnDDatnaDat, DatumVrednost);
await OnLoadPrometNedelja(KorisnikID, PomocnaDnDDatnaDatNedelja);
}
catch(Exception e)
{
//Handle Exception
}
}
Explanation
Many C# devs are taught "Never use async void", but this is one of the few use-cases for it.
Yes async void can be dangerous and here's why:
Cannot await an async avoid method
Can lead to race conditions
Difficult to catch an Exception thrown by async void methods
E.g. the following try/catch block will not catch the Exception thrown here:
public MyConstructor()
{
try
{
//Cannot await `async void`
AsyncVoidMethodWithException();
}
catch(Exception e)
{
//Will never catch the `Exception` thrown in `AsyncVoidMethodWithException` because `AsyncVoidMethodWithException` cannot be awaited
}
//code here will be executing by the time `AsyncVoidMethodWithException` throws the exception
}
async void AsyncVoidMethodWithException()
{
await Task.Delay(2000);
throw new Exception();
}
That being said, as long as we wrap the contents of our entire async void in a try/catch block, we will be able to catch the exception, like so:
public MyConstructor()
{
AsyncVoidMethodWithException();
}
async void AsyncVoidMethodWithException()
{
try
{
await Task.Delay(2000);
throw new Exception();
}
catch(Exception e)
{
//Exception will be caught and successfully handled
}
}
SafeFireAndForget
I created a library to help with this and its additional benefit is that it avoids writing async void code that could be potentially misused by future devs.
It's open source and also available on NuGet:
Source Code
NuGet Package
SafeFireAndForget
SafeFireAndForget allows us to safely execute a Task whilst not blocking the calling thread and without waiting for it to finish before moving to the next line of code.
Below is a simplified version of SafeFireAndForget that you can add to your project.
However, I recommend copy/pasting its complete source code or adding its NuGet Package to your library to get a more robust implementation
public static async void SafeFireAndForget<TException>(this Task task, Action<TException> onException = null, bool continueOnCapturedContext = false) where TException : Exception
{
try
{
await task.ConfigureAwait(continueOnCapturedContext);
}
catch (TException ex) when (onException != null)
{
onException(ex);
}
}
Using SafeFireAndForget
To use SafeFireAndForget, append it to your method call like so:
OnLoadPrometDanKorisnikDatum(KorisnikID, PomocnaDnDDatnaDat, DatumVrednost).SafeFireAndForget();
OnLoadPrometNedelja(KorisnikID, PomocnaDnDDatnaDatNedelja).SafeFireAndForget();
To handle any Exception thrown by that Task, use onException. Here's an example that prints the Exception to the Debug Console:
OnLoadPrometDanKorisnikDatum(KorisnikID, PomocnaDnDDatnaDat, DatumVrednost).SafeFireAndForget(ex => Debug.WriteLine(ex));
OnLoadPrometNedelja(KorisnikID, PomocnaDnDDatnaDatNedelja).SafeFireAndForget(ex => Debug.WriteLine(ex));
I am studying C# Asnc-await pattern and currently reading Concurrency in C# Cookbook from S. Cleary
He discusses wrapping old non TAP async patterns with TaskCompletionSource (TCS) into TAP constructs.
What I dont get is, why he just returns the Task property of the TCS object instead of awaiting it TCS.Task ?
Here is the example code:
Old method to wrap is DownloadString(...):
public interface IMyAsyncHttpService
{
void DownloadString(Uri address, Action<string, Exception> callback);
}
Wrapping it into TAP construct:
public static Task<string> DownloadStringAsync(
this IMyAsyncHttpService httpService, Uri address)
{
var tcs = new TaskCompletionSource<string>();
httpService.DownloadString(address, (result, exception) =>
{
if (exception != null)
tcs.TrySetException(exception);
else
tcs.TrySetResult(result);
});
return tcs.Task;
}
Now why not just do it that way:
public static async Task<string> DownloadStringAsync(
this IMyAsyncHttpService httpService, Uri address)
{
var tcs = new TaskCompletionSource<string>();
httpService.DownloadString(address, (result, exception) =>
{
if (exception != null)
tcs.TrySetException(exception);
else
tcs.TrySetResult(result);
});
return await tcs.Task;
}
Is there a functional difference between the two? Is the second one not more natural?
By marking it async, the compiler will generate warnings, that it should be considered to await this method
You don't have to mark your own method as async in order to get the "Task not awaited" warning. The following code generates the same warning for the calls to both T and U:
static async Task Main(string[] args)
{
Console.WriteLine("Done");
T();
U();
Console.WriteLine("Hello");
}
public static Task T()
{
return Task.CompletedTask;
}
public static async Task U()
{
await Task.Yield();
return;
}
Whenever you find yourself with a method only containing a single await and that being the last thing it does (except possibly returning the awaited value), you should ask yourself what value it's adding. Aside from some differences in exception handing, it's just adding an extra Task into the mix.
await is generally a way of indicating "I've got no useful work to do right now, but will have when this other Task is finished" which of course isn't true (you've got no other work to do later). So skip the await and just return what you would have awaited instead.
Your version is strictly more complex -- instead of just returning the task, you make the method async, and await the task you could just be returning.
There is one subtle practical difference (other than the version with await being slower to run).
In the first example, if DownloadString throws an exception (rather than calling the delegate you pass it with exception set), then that exception will bubble through your call to DownloadStringAsync.
In the second, the exception is packaged into the Task returned from DownloadStringAsync.
So, assuming that DownloadString throws this exception (and no other exceptions occur):
Task<string> task;
try
{
task = httpService.DownloadStringAsync(...);
}
catch (Exception e)
{
// Catches the exception ONLY in your first non-async example
}
try
{
await task;
}
catch (Exception e)
{
// Catches the exception ONLY in your second async example
}
You probably don't care about the distinction - if you just write:
await httpService.DownloadStringAsync(...);
you won't notice the difference.
Again, this only happens if the DownloadString method itself throws. If it instead calls the delegate you give it with exception set to a value, then there is no observable difference between your two cases.
Folks, thanks for the helpful comments.
In the meantime I have read the sources referenced here and also investigated the matter further: Influenced by https://blog.stephencleary.com/2016/12/eliding-async-await.html I have come to the conclusion, that its best practice to include async-await by default even in synchronous methods of the async function chain and only omit async await when the circumstances clearly indicate that the method will not potentially behave differently as expected from an async method en edge scenarios.
Such as: the synchronous method is short, simple and has no operations inside which could throw an exception. If the synchronous method throws an exception the caller will get an exception in the calling line instead of the line where the Task is awaited. This is clearly a change from expected behavior.
For example handing over call parameters to the next layer unchanged is a situation which imo permits omitting async-await.
Read my answer why returning the task is not a good idea: What is the purpose of "return await" in C#?
Basically you break your call stack if you don't use await.
Related to this answer,
If I truly do want to "Fire and Forget" a method that does return a task, and (for simplicity) let's assume that the method isn't expected to throw any exceptions. I can use the extension method listed in the answer:
public static void Forget(this Task task)
{
}
Using this approach, if there are bugs in action of the Task that cause an exception to be thrown then when the unexpected exception is thrown, the exception will be swallowed and go unnoticed.
Question: Wouldn't it be more appropriate in this scenario for the extension method to be of the form:
public static async void Forget(this Task task)
{
await task;
}
So that programming errors throw an exception and get escalated (usually bringing down the process).
In the case of a method with expected (and ignorable) exceptions, the method would need to become more elaborate (as an aside, any suggestions on how to construct a version of this method that would take a list of acceptable and ignorable exception types?)
It depends on the semantics you want. If you want to ensure exceptions are noticed, then yes, you could await the task. But in that case it's not truly "fire and forget".
A true "fire and forget" - in the sense that you don't care about when it completes or whether it completes successfully or with error - is extremely rare.
Edit:
For handling exceptions:
public static async void Forget(this Task task, params Type[] acceptableExceptions)
{
try
{
await task.ConfigureAwait(false);
}
catch (Exception ex)
{
// TODO: consider whether derived types are also acceptable.
if (!acceptableExceptions.Contains(ex.GetType()))
throw;
}
}
Note that I recommend using await instead of ContinueWith. ContinueWith has a surprising default scheduler (as noted on my blog) and Task.Exception will wrap the actual exception in an AggregateException, making the error handling code more cumbersome.
In the linked question I initially wanted to use static void Forget(this Task task) in the following context:
var task = DoWorkAsync();
QueueAsync(task).Forget();
// ...
async Task QueueAsync(Task task)
{
// keep failed/cancelled tasks in the list
// they will be observed outside
_pendingTasks.Add(task);
await task;
_pendingTasks.Remove(tasks)
}
It looked great, but then I realized that fatal exceptions possibly thrown by _pendingTasks.Add / _pendingTasks.Remove would be gone unobserved and lost, which is not good.
So I simply made QueueTask an async void method, what it essentially is:
var task = DoWorkAsync();
QueueAsync(task);
// ...
async void QueueAsync(Task task)
{
// keep failed/cancelled tasks in the list
// they will be observed outside
_pendingTasks.Add(task);
try
{
await task;
}
catch
{
return;
}
_pendingTasks.Remove(tasks)
}
As much as I don't like empty catch {}, I think it makes sense here.
In this scenario, keeping async Task QueueAsync() and using async void Forget(this Task task) like you propose would be on overkill, IMO.
Yes if you were interested in whether or not the task threw an exception then you would need to await the result, but on the flipside, that pretty much defeats the purpose of "fire & forget".
In the scenario where you want to know if something bad happened then the recommended way of doing this is to use a continuation e.g.
public static void ForgetOrThrow(this Task task)
{
task.ContinueWith((t) => {
Console.WriteLine(t.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
}
Is there a MS "best practice" or contract agreement when implementing a method that returns a Task in regards to throwing exceptions? This came up when writing unit tests and I was trying to figure out if I should to test/handle this condition (I recognize that the answer could be "defensive coding", but I don't want that to be the answer).
i.e.
Method must always return a Task, which should contain the thrown Exception.
Method must always return a Task, except when the method supplies invalid arguments (i.e. ArgumentException).
Method must always return a Task, except when the developer goes rogue and does what he/she wants (jk).
Task Foo1Async(string id){
if(id == null){
throw new ArgumentNullException();
}
// do stuff
}
Task Foo2Async(string id){
if(id == null){
var source = new TaskCompletionSource<bool>();
source.SetException(new ArgumentNullException());
return source.Task;
}
// do stuff
}
Task Bar(string id){
// argument checking
if(id == null) throw new ArgumentNullException("id")
try{
return this.SomeService.GetAsync(id).ContinueWith(t => {
// checking for Fault state here
// pass exception through.
})
}catch(Exception ex){
// handling more Fault state here.
// defensive code.
// return Task with Exception.
var source = new TaskCompletionSource<bool>();
source.SetException(ex);
return source.Task;
}
}
I've asked a somewhat similar question recently:
Handling exceptions from the synchronous part of async method.
If the method has an async signature, it doesn't matter if you throw from the synchronous or asynchronous part of method. In both cases, the exception will be stored inside the Task. The only difference is that the resulting Task object will be instantly completed (faulted) in the former case.
If the method doesn't have async signature, the exception may be thrown on the caller's stack frame.
IMO, in either case the caller should not make any assumption about whether the exception has been thrown from the synchronous or asynchronous part, or whether the method has async signature, at all.
If you really need to know if the task has completed synchronously, you can always check its Task.Completed/Faulted/Cancelled status, or Task.Exception property, without awaiting:
try
{
var task = Foo1Async(id);
// check if completed synchronously with any error
// other than OperationCanceledException
if (task.IsFaulted)
{
// you have three options here:
// 1) Inspect task.Exception
// 2) re-throw with await, if the caller is an async method
await task;
// 3) re-throw by checking task.Result
// or calling task.Wait(), the latter works for both Task<T> and Task
}
}
catch (Exception e)
{
// handle exceptions from synchronous part of Foo1Async,
// if it doesn't have `async` signature
Debug.Print(e.ToString())
throw;
}
However, normally you should just await the result, without caring if the task has completed synchronously or asynchronously, and which part has possibly thrown. Any exception will be re-thrown on the caller context:
try
{
var result = await Foo1Async(id);
}
catch (Exception ex)
{
// handle it
Debug.Print(ex.ToString());
}
This works for unit testing too, as long as the async method returns a Task (the Unit Test engine doesn't support async void method, AFAIK, which makes sense: there is no Task to keep track of and await).
Back to your code, I'd put it this way:
Task Foo1Async(string id){
if(id == null) {
throw new ArgumentNullException();
}
// do stuff
}
Task Foo2Async(string id) {
if(id == null){
throw new ArgumentNullException();
}
// do stuff
}
Task Bar(string id) {
// argument checking
if(id == null) throw new ArgumentNullException("id")
return this.SomeService.GetAsync(id);
}
Let the caller of Foo1Async, Foo2Async, Bar deal with the exceptions, rather than capturing and propagating them manually.
I know that Jon Skeet is a fan of doing precondition-style checks in a separate synchronous method so that they are thrown directly.
However, my own opinion is "it doesn't matter". Consider Eric Lippert's exception taxonomy. We all agree that exogenous exceptions should be placed on the returned Task (not thrown directly on the caller's stack frame). Vexing exceptions should be completely avoided. The only types of exceptions in question are boneheaded exceptions (e.g., argument exceptions).
My argument is that it doesn't matter how they're thrown because you shouldn't write production code that catches them. Your unit tests are the only code that should be catching ArgumentException and friends, and if you use await then it doesn't matter when they're thrown.
The general case when methods return tasks is because they are asynchronous methods. In these cases it's common that an exception in the synchronous part of the method should be thrown just like in any other method, and in the asynchronous part should be stored inside the returned Task (automatically by calling an async method or anonymous delegate).
So, in the simple cases like invalid parameters simply throw an exception like in Foo1Async. In the more complex case regarding the asynchronous operation set an exception on the returned task like in Foo2Async
This answer assumes you're referring to Task returning methods that aren't marked with async. In those that are you have no control over the task being created, and any exception would automatically be stored in that task (so the question would be irrelevant).
I have an async method which returns no data:
public async Task MyAsyncMethod()
{
// do some stuff async, don't return any data
}
I'm calling this from another method which returns some data:
public string GetStringData()
{
MyAsyncMethod(); // this generates a warning and swallows exceptions
return "hello world";
}
Calling MyAsyncMethod() without awaiting it causes a "Because this call is not awaited, the current method continues to run before the call is completed" warning in visual studio. On the page for that warning it states:
You should consider suppressing the warning only if you're sure that you don't want to wait for the asynchronous call to complete and that the called method won't raise any exceptions.
I'm sure I don't want to wait for the call to complete; I don't need to or have the time to. But the call might raise exceptions.
I've stumbled into this problem a few times and I'm sure it's a common problem which must have a common solution.
How do I safely call an async method without awaiting the result?
Update:
For people suggesting that I just await the result, this is code that is responding to a web request on our web service (ASP.NET Web API). Awaiting in a UI context keeps the UI thread free, but awaiting in a web request call will wait for the Task to finish before responding to the request, thereby increasing response times with no reason.
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.
You should first consider making GetStringData an async method and have it await the task returned from MyAsyncMethod.
If you're absolutely sure that you don't need to handle exceptions from MyAsyncMethod or know when it completes, then you can do this:
public string GetStringData()
{
var _ = MyAsyncMethod();
return "hello world";
}
BTW, this is not a "common problem". It's very rare to want to execute some code and not care whether it completes and not care whether it completes successfully.
Update:
Since you're on ASP.NET and wanting to return early, you may find my blog post on the subject useful. However, ASP.NET was not designed for this, and there's no guarantee that your code will run after the response is returned. ASP.NET will do its best to let it run, but it can't guarantee it.
So, this is a fine solution for something simple like tossing an event into a log where it doesn't really matter if you lose a few here and there. It's not a good solution for any kind of business-critical operations. In those situations, you must adopt a more complex architecture, with a persistent way to save the operations (e.g., Azure Queues, MSMQ) and a separate background process (e.g., Azure Worker Role, Win32 Service) to process them.
The answer by Peter Ritchie was what I wanted, and Stephen Cleary's article about returning early in ASP.NET was very helpful.
As a more general problem however (not specific to an ASP.NET context) the following Console application demonstrates the usage and behavior of Peter's answer using Task.ContinueWith(...)
static void Main(string[] args)
{
try
{
// output "hello world" as method returns early
Console.WriteLine(GetStringData());
}
catch
{
// Exception is NOT caught here
}
Console.ReadLine();
}
public static string GetStringData()
{
MyAsyncMethod().ContinueWith(OnMyAsyncMethodFailed, TaskContinuationOptions.OnlyOnFaulted);
return "hello world";
}
public static async Task MyAsyncMethod()
{
await Task.Run(() => { throw new Exception("thrown on background thread"); });
}
public static void OnMyAsyncMethodFailed(Task task)
{
Exception ex = task.Exception;
// Deal with exceptions here however you want
}
GetStringData() returns early without awaiting MyAsyncMethod() and exceptions thrown in MyAsyncMethod() are dealt with in OnMyAsyncMethodFailed(Task task) and not in the try/catch around GetStringData()
I end up with this solution :
public async Task MyAsyncMethod()
{
// do some stuff async, don't return any data
}
public string GetStringData()
{
// Run async, no warning, exception are catched
RunAsync(MyAsyncMethod());
return "hello world";
}
private void RunAsync(Task task)
{
task.ContinueWith(t =>
{
ILog log = ServiceLocator.Current.GetInstance<ILog>();
log.Error("Unexpected Error", t.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
}
This is called fire and forget, and there is an extension for that.
Consumes a task and doesn't do anything with it. Useful for fire-and-forget calls to async methods within async methods.
Install nuget package.
Use:
MyAsyncMethod().Forget();
EDIT: There is another way I've been rather using lately:
_ = MyAsyncMethod();
Not the best practice, you should try avoiding this.
However, just to address "Call an async method in C# without await", you can execute the async method inside a Task.Run. This approach will wait until MyAsyncMethod finish.
public string GetStringData()
{
Task.Run(()=> MyAsyncMethod()).Result;
return "hello world";
}
await asynchronously unwraps the Result of your task, whereas just using Result would block until the task had completed.
If you want to wrap it in a helper class:
public static class AsyncHelper
{
public static void Sync(Func<Task> func) => Task.Run(func).ConfigureAwait(false);
public static T Sync<T>(Func<Task<T>> func) => Task.Run(func).Result;
}
and call like
public string GetStringData()
{
AsyncHelper.Sync(() => MyAsyncMethod());
return "hello world";
}
I'm late to the party here, but there's an awesome library I've been using which I haven't seen referenced in the other answers
https://github.com/brminnick/AsyncAwaitBestPractices
If you need to "Fire And Forget" you call the extension method on the task.
Passing the action onException to the call ensures that you get the best of both worlds - no need to await execution and slow your users down, whilst retaining the ability to handle the exception in a graceful manner.
In your example you would use it like this:
public string GetStringData()
{
MyAsyncMethod().SafeFireAndForget(onException: (exception) =>
{
//DO STUFF WITH THE EXCEPTION
});
return "hello world";
}
It also gives awaitable AsyncCommands implementing ICommand out the box which is great for my MVVM Xamarin solution
Typically async method returns Task class. If you use Wait() method or Result property and code throws exception - exception type gets wrapped up into AggregateException - then you need to query Exception.InnerException to locate correct exception.
But it's also possible to use .GetAwaiter().GetResult() instead -
it will also wait async task, but will not wrap exception.
So here is short example:
public async Task MyMethodAsync()
{
}
public string GetStringData()
{
MyMethodAsync().GetAwaiter().GetResult();
return "test";
}
You might want also to be able to return some parameter from async function - that can be achieved by providing extra Action<return type> into async function, for example like this:
public string GetStringData()
{
return MyMethodWithReturnParameterAsync().GetAwaiter().GetResult();
}
public async Task<String> MyMethodWithReturnParameterAsync()
{
return "test";
}
Please note that async methods typically have ASync suffix naming, just to be able to avoid collision between sync functions with same name. (E.g. FileStream.ReadAsync) - I have updated function names to follow this recommendation.
I guess the question arises, why would you need to do this? The reason for async in C# 5.0 is so you can await a result. This method is not actually asynchronous, but simply called at a time so as not to interfere too much with the current thread.
Perhaps it may be better to start a thread and leave it to finish on its own.
On technologies with message loops (not sure if ASP is one of them), you can block the loop and process messages until the task is over, and use ContinueWith to unblock the code:
public void WaitForTask(Task task)
{
DispatcherFrame frame = new DispatcherFrame();
task.ContinueWith(t => frame.Continue = false));
Dispatcher.PushFrame(frame);
}
This approach is similar to blocking on ShowDialog and still keeping the UI responsive.
Maybe I'm too naive but, couldn't you create an event that is raised when GetStringData() is called and attach an EventHandler that calls and awaits the async method?
Something like:
public event EventHandler FireAsync;
public string GetStringData()
{
FireAsync?.Invoke(this, EventArgs.Empty);
return "hello world";
}
public async void HandleFireAsync(object sender, EventArgs e)
{
await MyAsyncMethod();
}
And somewhere in the code attach and detach from the event:
FireAsync += HandleFireAsync;
(...)
FireAsync -= HandleFireAsync;
Not sure if this might be anti-pattern somehow (if it is please let me know), but it catches the Exceptions and returns quickly from GetStringData().
The solution is start the HttpClient into another execution task without sincronization context:
var submit = httpClient.PostAsync(uri, new StringContent(body, Encoding.UTF8,"application/json"));
var t = Task.Run(() => submit.ConfigureAwait(false));
await t.ConfigureAwait(false);
It is straightforward, just call asyncMethod().Result to call without await. Below is the sample code and here is the fiddle
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var asyncDemo = new AsyncDemo();
asyncDemo.TestMethod1Void().Wait();
var result = asyncDemo.TestMethod1().Result;
Console.WriteLine(result);
}
}
public class AsyncDemo {
public async Task<string> TestMethod1()
{
Thread.Sleep(1000);
return "From Async Method";
}
public async Task TestMethod1Void()
{
Thread.Sleep(1000);
Console.WriteLine("Async Void Method");
}
}