How to call an async function synchronized without blocking the main thread? - c#

I wrote a simple console application to test ConfigureAwait(false) for fixing the problem of calling an async function in a synchronized way. This is how I simulate an event and trying to call an async function in a sync way.
public static class Test2
{
private static EventHandler<int> _somethingEvent;
public static void Run()
{
_somethingEvent += OnSomething;
_somethingEvent(null, 10);
Console.WriteLine("fetch some other resources");
Console.ReadLine();
}
private static void OnSomething(object sender, int e)
{
Console.WriteLine($"passed value : {e}");
FakeAsync().Wait();
}
private static async Task FakeAsync()
{
await Task.Delay(2000).ConfigureAwait(false);
Console.WriteLine($"task completed");
}
}
the output of the code is like this:
passed value : 10
task completed
fetch some other resources
And when I change the OnSomething function to async void like this:
private static async void OnSomething(object sender, int e)
{
Console.WriteLine($"passed value : {e}");
await FakeAsync();
}
The output will change to this:
passed value : 10
fetch some other resources
task completed
You can see fetch some other resources is occurred before task completed section and this is my desired result.
My question is how can I achieve the same result by calling the async function synchronized like the first signature I wrote for the OnSomething function?
How could I use ConfigureAwait(false) to help me in this situation? Or maybe I am not using it properly.

I wrote a simple console application to test ConfigureAwait(false) for fixing the problem of calling an async function in a synchronized way.
There's a couple of problems with this.
ConfigureAwait(false) is not a "fix" for the "problem" of calling an asynchronous function synchronously. It is one possible hack that works in some situations, but it's not generally recommended because you have to use ConfigureAwait(false) everywhere in the entire transitive closure of that function - including second- and third-party calls - and if you just miss one, there is still the possibility of a deadlock. The best solution for the problem of calling an asynchronous function from a synchronous function is to change the calling function to be asynchronous (go "async all the way"). Sometimes this isn't possible and you need a hack, but there is no hack that works in every scenario.
The deadlock issue you're trying to avoid has two ingredients: blocking a thread on a task, and a single-threaded context. Console applications do not have a single-threaded context, so in a Console application it's as though all your code uses ConfigureAwait(false) everywhere.
My question is how can I achieve the same result by calling the async function synchronized like the first signature I wrote for the OnSomething function?
The calling code will either block on the asynchronous code (e.g., Wait), or it will not (e.g., await). You can't block on the asynchronous code and continue executing. The calling thread must either continue executing or block; it can't do both.

It's because when you call _somethingEvent(null, 10);, OnSomething isn't being awaited, so the following Console.WriteLine("fetch some other resources"); will be allowed to run straight after await FakeAsync(); is executed.
If you don't need to await the completion of OnSomething before continuing, just do a fire and forget:
private static void OnSomething(object sender, int e)
{
Console.WriteLine($"passed value : {e}");
Task.Run(() => FakeAsync());
}

Related

Sync calling async nested methods - Will async work down the path?

I have async methods inside my libraries and the top level call is made at the handler of AWS Lambda functions synchronously (for some reason not to discuss here). I wonder if any calls made down the track be asynchronous by any chance? or because the first caller does it synchronously will everything be synchronous?
public void LambdaHandler(Input inp, ILambdaContext context)
{
method1().GetAwaiter().GetResult();
}
private async Task method1()
{
await method2();
await method3();
}
private async Task method2()
{
//do something
}
private async Task method3()
{
//do something
}
method2 and method3 will do whatever they always have done. If they are purely synchronous behind a Task API, then they will continue to be synchronous; if they are asynchronous, then they will continue to be asynchronous. The only question here is: what will LambdaHandler do, and the answer to that is simply:
it will block until they are complete
If they are already complete synchronously, then fine; if they aren't, then you've tied up a thread in a sync-over-async block. This could by itself cause a deadlock if your code uses a sync-context or task-scheduler that only has a single worker (which isn't uncommon), as the thread that the async code will need to do any post-processing will be stuck waiting at GetResult(). So the async part can't complete, and GetResult() can't complete.
You should avoid sync-over-async like the plague. There is a reason it is considered an anti-pattern.
The methods down below the call stack will run asynchronously.
But the entire thing would block and wait for the task to complete.
The better way is to modify LambdaHandler to return Task and use await instead of calling the GetAwaiter.
Help link

Avoid async from spreading in method signatures

What prevents me from constantly using the async/wait pattern in my .net code is that once you create an async method the async keyword tends to spread thru my code forcing me to make all methods async. Is there a pattern to stop this efficiently?
What prevents me from constantly using the async/wait pattern in my .net code is that once you create an async method the async keyword tends to spread thru my code forcing me to make all methods async. Is there a pattern to stop this efficiently?
Let me ask you this, then: why are you using async/await? You need to take a step back and decide if you want the benefits of asynchronous code. If you do want those benefits, then your code must be asynchronous. As soon as you block a thread, you lose all the benefits of async. So really, why use asynchronous code at all, if you're just going to block a thread anyway?
That said, there are some scenarios where a partially-async stack makes sense. For example, if your code base is temporarily in a transition state. In this case, you can use one of the hacks described in my article on brownfield async:
Blocking directly (may cause deadlocks).
Blocking on a thread pool thread (executes code on a different thread and different context, may cause unexpected parallelism).
Blocking on the current thread with a thread pool context (executes code in a different context, may cause unexpected parallelism).
Blocking on a thread with a single-threaded context (executes code on a different thread and different context).
Blocking on a nested message loop (may cause unexpected reentrancy).
All of these are hacks, and all have different drawbacks. There is no hack that works in every scenario.
As commented earlier you should go async all the way...
In some cases we use a litle helper class to cut off the async pattern. This class alows you to wait for the result without ending up with a deadlock by replacing the SynchronizationContext.
public class NoSynchronizationContextScope : IDisposable
{
private readonly SynchronizationContext synchronizationContext;
public NoSynchronizationContextScope()
{
synchronizationContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
}
public void Dispose() => SynchronizationContext.SetSynchronizationContext(synchronizationContext);
}
void fn()
{
using (new NoSynchronizationContextScope())
{
fnAsync().Wait();
// or
// var result = fnAsync().Result();
// in case you have to wait for a result
}
}
In the very particular case of a method that you want to start running but not wait for the result of (i.e. triggering an event handler) you can use async void. Just make sure you catch all the errors at that point:
public async void DoSomething() {
try {
var o = await DoThing1();
await DoThing2(o);
} catch (Exception e) {
// Log the error somewhere (to a file, database, etc.)
}
}
You can use async method and invoke not async method in task so outer method will behave like async and inner method is still sync.
public async Task OuterFuncAsync()
{
await Task.Run(() => InnerFunc());
}

Ignoring the return value from an async Task method

Here's the scenario: In my WPF app I'd like to keep a loop running at all times that does various things. This pattern came to mind:
void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
SomeProcessAsync(); //throw away task
}
async Task SomeProcessAsync()
{
while (true)
{
DoSomething();
await Task.Delay(1000);
}
}
The call triggers a warning since the return value is unused. What is the cleanest way to silence that warning?
#pragma warning disable 4014
AddItemsAsync(); //throw away task
#pragma warning restore 4014
This works but it looks so nasty!
Btw, I also could have used a timer but I liked the simplicity of this loop.
As already mentioned in chris' answer, the right solution here is to turn the event handler into an async void method and then use await, so that exceptions are propagated correctly.
But if you really want to ignore the Task, then you can assign it to a variable:
var ignored = SomeProcessAsync();
Or in C# 7.0, you can use discard:
_ = SomeProcessAsync();
You can make the event handler async:
async void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
await SomeProcessAsync(); //throw away task
}
Normally, async void is bad, but it's necessary when an event handler is async and exceptions should be handled here instead of in whatever calls this. You can (and should) use the normal ConfigureAwait(false) if SomeProcessAsync doesn't need the UI context.
My solution is to silence the compiler warning with a little helper method that is reusable:
static class TaskHelpers
{
/// <summary>Signifies that the argument is intentionally ignored.</summary>
public static void DiscardTask(this Task ignored)
{
}
}
And the call looks like this:
AddItemsAsync().DiscardTask();
That's clean and self-documenting. Still looking for a better name for the helper.
Async-await uses threads from the thread pool. Although the number of threads in the thread pool is fairly large, and possibly adjustable, it is still a limited number of threads.
The threads in the thread pool are optimized for short living tasks. They start and finish fast, the results from these thread can be accessed fairly easily. But these advantages come with a cost. If not, all threads would be threads from the thread pool.
If you want to let your thread do something for a fairly long time, it is best to use a regular System.Threading.Thread, possibly wrapped in a System.ComponentModel.BackgroundWorker.
Better to create a task with your delegate code
Task.Factory.StartNew( () => {} );

Winforms call to async method hangs up program

I have been working around this problem for a while, but now I would really like to understand what goes wrong. I have a rather simple application (it's a turtoise SVN plugin for youtrack, but I can reproduce the problem with a trivial winforms app).
I have an async method ResolveIssue
public async Task<bool> ResolveIssue(Issue issue, int revision, string[] pathList)
{
await Task.Delay(1000);
return true;
}
All I have to do to create a deadlock is call this async method in a Button event handler, and call Task.Wait or Task.Result, like this
private void buttonOk_Click(object sender, System.EventArgs e)
{
var asyncResolvedIssue = api.ResolveIssue(issue, revision, pathList);
if (asyncResolvedIssue.Result) {} // <== deadlock!
}
Now I understand it's rather weird to have an async method and actively wait for it, but why would it generate a deadlock?!
Your problem is because you are blocking the UI thread when you call .Result and you told the continuation after Task.Delay to run on the UI thread. So you are blocking the UI waiting for a task that is blocked on waiting for the UI to become free, a classic deadlock.
Two solutions. First make the button click async too.
private async void buttonOk_Click(object sender, System.EventArgs e)
{
var asyncResolvedIssue = api.ResolveIssue(issue, revision, pathList);
if (await asyncResolvedIssue) {} // <== no deadlock!
}
Event handlers are the only place you are allowed to do async void.
The other option is tell Task.Delay it does not need to have the rest of its function run on the UI thread by setting ConfigureAwait(bool) to false.
public async Task<bool> ResolveIssue(Issue issue, int revision, string[] pathList)
{
await Task.Delay(1000).ConfigureAwait(false);
return true;
}
Now the line of code after the Task.Delay will run on a threadpool thread instead of the UI thread and will not be blocked by the fact that the UI thread is currently blocked.

C# have async function call synchronous function or synchronous function call async function

I'm writing a C# .Net 4.5 library for doing common sql database operations (backup, restore, execute script, etc.). I want to have both synchronous and asynchronous functions for each operation, as this library will be used by both console and GUI apps, but I don't want to duplicate code everywhere. So as I see it, I have two options:
Write the code that does the work in a synchronous function, and then just wrap it in a task for the async function, like so:
public void BackupDB(string server, string db)
{
// Do all of the work and long running operation here
}
public async Task BackupDBAsync(string server, string db)
{
await Task.Factory.StartNew(() => BackupDB(server, db)).ConfigureAwait(false);
}
Write the code that does the work in an asynchronous function, and call it from a synchronous function using .Wait():
public async Task BackupDBAsync(string server, string db)
{
// Do all of the work and long running operation here, asynchronously.
}
public void BackupDB(string server, string db)
{
BackupDBAsync(server, db).Wait(); // Execution will wait here until async function finishes completely.
}
Is one option better than the other? Is one a best practice? Or are there any other (better) alternatives?
I know that one caveat to using .Wait() is that all of the await statements in the async function have to use .ConfigureAwait(false) to avoid deadlocks (as discussed here), but since I'm writing a library that will never need to access the UI or WebContext I am safe to do that.
I'll note too that the SQL library typically also has both synchronous and async functions that can be used, so if doing the work in the sync function, I would call their sync function, and if doing the work in the async function, I would call their async function.
Thoughts/suggestions are appreciated.
-- edit: I've also posted this question on the MSDN forums here to try and get an official MS response --
I want to have both synchronous and asynchronous functions for each operation, as this library will be used by both console and GUI apps, but I don't want to duplicate code everywhere.
The best answer is: don't.
Stephen Toub has two excellent blog posts on this topic:
Should I expose asynchronous wrappers for synchronous methods?
Should I expose synchronous wrappers for asynchronous methods?
He recommends exposing asynchronous methods as asynchronous, and synchronous methods as synchronous. If you need to expose both, then encapsulate common functionality in private (synchronous) methods, and duplicate the async/sync differences.
I had a similar situation where some applications needed the data to be loaded synchronously and others asyc. I decided to created an interface that I called my dataloader:
public interface IIMViewModelDL {
void LoadProjects(AssignProjects callback);
}
The AssignProjects callback is just a simple delegate that takes in the returned list of projects:
public delegate void AssignProjects(IEnumerable<Project> results);
Now, the beauty of this is that you can work with the interface without knowing whether you are dealling in sync or async.
Three classes are created: one base, one sync, and one async:
public abstract class BaseViewModelDL {
protected IEnumerable<Project> LoadProjects() {
BaseServiceClient client = new BaseServiceClient();
return client.Projects();
}
public class SynchronousViewModelDL : BaseViewModelDL, IIMViewModelDL {
public void LoadProjects(AssignProjects callback) {
callback(base.LoadProjects());
}
public class AsyncIMViewModelDL : BaseViewModelDL, IIMViewModelDL {
public void LoadProjects(AssignProjects callback) {
BackgroundWorker loadProjectsAsync = new BackgroundWorker();
loadProjectsAsync.DoWork += new DoWorkEventHandler(LoadProjectsAsync_DoWork);
loadProjectsAsync.RunWorkerCompleted += new RunWorkerCompletedEventHandler(LoadProjectsAsync_RunWorkerCompleted);
loadProjectsAsync.RunWorkerAsync(callback);
}
void LoadProjectsAsync_DoWork(object sender, DoWorkEventArgs e) {
var results = new ObservableCollection<Project>(base.LoadProjects());
e.Result = new object[] { results, e.Argument };
}
void LoadProjectsAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
AssignProjects callback = (AssignProjects)((object[])e.Result)[1];
IEnumerable<Project> results = (IEnumerable<Project>)((object[])e.Result)[0];
callback(results);
}
Now, in your application, you can decide how you want to load data...this could be injected through an IoC container, but is hard coded for demo purposes:
private ViewModelDataLoaders.IIMViewModelDL dataLoader = new ViewModelDataLoaders.AsyncIMViewModelDL();
Now, your calling code looks the same and is none the wiser to whether it is async or sync:
private void LoadProjects() {
dataLoader.LoadProjects(
delegate(IEnumerable<Project> results) {
Projects = new ObservableCollection<Project>(results);
});
}
I use this regularly for unit testing (sync), WPF applications (async), and console applications (sync).
There does not seem to be a point to simply mark a method as async without using an await. Marking it as async does not make it asynchronous, it allows you to use awaits (the code executed in the await is what happens asynchronously, and then the rest of the async method will also be done asynchronously) in the body of the method:
Typically, a method modified by the async keyword contains at least one await expression or statement. The method runs synchronously until it reaches the first await expression, at which point it is suspended until the awaited task is complete. In the meantime, control is returned to the caller of the method. If the method does not contain an await expression or statement, then it executes synchronously. A compiler warning alerts you to any async methods that don't contain await because that situation might indicate an error. For more information, see Compiler Warning CS4014.
From: async

Categories

Resources