My understanding is that if you call async code synchronously it can cause deadlock when it needs to synchronize back to the UI thread to modify UI elements or if you need to access ASP.NET HttpContext.Current. There are workarounds to solve this problem as mentioned here:
https://learn.microsoft.com/en-us/archive/msdn-magazine/2015/july/async-programming-brownfield-async-development
How to call asynchronous method from synchronous method in C#?
I was looking at the "The Thread Pool Hack" approach from the first link but I need to call GetAwaiter().GetResult() directly from the async code which is already called from a new thread e.g:
//MyWork.DoWork must execute in a separate thread due legacy code that I can't refactor right now.
public class SomeClass {
try {
var myThread = new Thread(MyWork.DoWork);
myThread.Start();
} catch (Exception ex) {
//Handle exceptions
}
}
public class MyWork {
public static bool DoWork(){
var response = MyHttpClient.MakeRequestAsync(params)
.GetAwaiter()
.GetResult();
if(!response.Succeed){
//add logs and other stuff
}
}
}
Also my call to MyHttpClient.MakeRequestAsync is NOT using .ConfigureAwait(false); and I can't add that since the same calls can be used in other places where it may need to synchronize back to the UI context
Is it safe to call .GetAwaiter().GetResult() directly on MyHttpClient.MakeRequestAsync since I'm already starting the work in a separate thread?
Once the MyHttpClient.MakeRequestAsync resumes will it resume the work in the same thread?
Update:
I cannot let the async pattern propagate I must use existing legacy code that uses the thread class so no refactoring allowed at the moment for SomeClass.
Related
I have a constructor that is called on UI thread in my WPF app. Inside of it, it calls async method but it must be done in a synchronous way. So I tried to call wait, but it caused deadlock an I understand why. So I introduced argument that indicates if method should be run in a asynchronous or synchronous manner. Something like this:
// constructor that is called on UI thread
public MyClass()
{
Method1(false).Wait();
}
public async Task Method1(bool runAsync)
{
await Method2(runAsync);
}
public async Task Method2(bool runAsync)
{
if (runAsync)
{
await Task.Run(() => Thread.Sleep(1000));
}
else
{
Thread.Sleep(1000);
}
}
I don't want to use ConfigureAwait because I want everything to run on UI thread. Will Method1(false).Wait(); ever cause a deadlock (is it safe to use)? I tested it a lot and it didn't, but I'm not sure. Finally, my real question is: if 'await Task.Run(...' is never executed, is my method completely synchronous? I found several posts on this subject, but none of them answers directly to my question.
I have a constructor that is called on UI thread in my WPF app. Inside of it, it calls async method but it must be done in a synchronous way.
I'm gonna stop you right there. The best solution is not to run synchronous/blocking code on the UI thread. That degrades your user experience. Instead, you should restructure your code so that you're never in this situation in the first place.
When a UI is being shown, the UI framework asks your code for the data to display. Your code should run synchronously and return immediately (not blocking). But your code also needs to do some asynchronous work in order to have the data to display. So there's a conflict there.
The solution is to design an intermediate state for your UI, e.g., a "loading..." message or a spinner. Then, when your code starts, it can synchronously/immediately display the "loading" state (and start the asynchronous operation), and when the asynchronous data arrives, the code updates the UI to the "final" state.
I discuss this pattern in more detail in my article on async MVVM data.
Instead of wrestling with async stuff at construction (your blocking solution isn't so good), why not write an async factory to spew out these objects?
class MyClass
{
public MyClass()
{
}
public async Task Method2(bool runAsync)
{
//async immediately
await Task.Delay(1000); //no Thread.Sleep. Blocking code != good
}
}
then
public MyClassFactory
{
public async Task<MyClass> GetAsync()
{
var c = new MyClass();
await c.Method2();
return c;
}
}
I'm trying to create a class that has synchronous methods and calls some other library methods which are asynchronous. For that reason I use Task.Result to wait for the async operation to finish. My methods are called by WPF app in synchronous way. This leads to a deadlock. I know that the best way is to make all my methods asynchronous but my situation requires them to be synchronous. From the other hand they use other library which is asynchronous.
My question is: How can I avoid the deadlock in such situation?
Steps to reproduce:
User hits a button in the app (method Button1_OnClick)
This method creates an instance of IPlugin and then calls its method RequestSomething()
This method then calls async library this way: asyncTarget.MethodFromAsyncLibrary("HelloFromPlugin").Result
The library calls back its method NotifyNewValueProgressAsync()
NotifyNewValueProgressAsync() delegates the call back to the WPF application
Since the UI context is blocked by this line asyncTarget.MethodFromAsyncLibrary("HelloFromPlugin").Result the callback in step 5 leads to a deadlock.
See code example below and related comments:
public class SyncAdapterPlugin : IPlugin, IProgressAsyncHandler
{
//Constructor and fields are omitted here
//This method is called from UI context by WPF application and it delegates synchronous call to asynchronous method
string IPlugin.RequestSomething()
{
//In order to be able to run the callback I need to capture current UI context
_context = TaskScheduler.FromCurrentSynchronizationContext();
var asyncTarget = new ClassFromMyLibrary1(this);
var resultFromAsyncLibrary = asyncTarget.MethodFromAsyncLibrary("HelloFromPlugin").Result; //Deadlock here!
return resultFromAsyncLibrary;
}
//This method does opposite, it delegates asynchronous callback to synchronous
async Task<bool> IProgressAsyncHandler.NotifyNewValueProgressAsync(string message)
{
//NotifyNewValueProgress method is implemented by WPF application and will update UI elements.
//That's why it's needed to run the callback on captured UI context.
Func<bool> work = () => _syncProgressHandler.NotifyNewValueProgress(message);
if (_context != null)
{
return await
Task.Factory.StartNew(work, CancellationToken.None, TaskCreationOptions.None, _context)
.ConfigureAwait(false);
}
return work();
}
}
Complete code example is here https://dotnetfiddle.net/i48sRc.
FYI, Some background on this issue you can also find in this SO question.
The plugin framework is fundamentally flawed. In particular, it requires a synchronous RequestSomething that expects to be able to call NotifyNewValueProgressAsync to update the UI. However, it's not possible to display a UI update while the UI thread is running a synchronous method.
This forces you to use one of the most dangerous and evil sync-over-async hacks: the nested message loop hack (as briefly described in my article on brownfield async). Since this is a WPF app, you'd use a nested dispatcher frame. The main pain with this hack is that it introduces reentrancy across your entire UI layer, which is the most subtle and difficult kind of concurrency problem.
By definition a synchronous method isn't going to be asynchronous. You will need to wrap the calls to the synchronous methods from the UI in a Task using TAP and await them there while making the method you await from asynchronous.
I have done a lot of search on this topic, and I read most of the posts here on this site regarding this topic, however I'm still confused and I need a straight forward answer. Here is my situation:
I have an established Winform application that I can't make it all 'async'. I'm forced now to use an external library that is all written as async functions.
In my application I have
/// <summary>
/// This function I can't change it to an 'async'
/// </summary>
public void MySyncFunction()
{
//This function is my point in my application where I have to call the
//other 'async' functions but I can't change the function itself to 'async'
try
{
//I need to call the MyAsyncDriverFunction() as if it is a synchronous function
//I need the driver function to finish execution and return before processing the code that follows it
//I also need to be able to catch any exceptions
MyAsyncDriverFunction();
//Rest of the code have to wait for the above function to return
}
catch (Exception exp)
{
//Need to be able to handle the exception thrown
//from the MyAsyncDriverFunction here.
}
}
public static async Task<IEnumerable<string>> MyAsyncDriverFunction()
{
try
{
var strCollection = await AsyncExternalLibraryFunction1();
var strCollection2 = await AsyncExternalLibraryFunction2();
return strCollection;
}
catch (Exception exp)
{
//Need to be able to catch an exception and re-throw it to the caller function
}
}
As outlined in the code, I need to be able to:
I can't change my MySyncFunction to an async
Call the "MyAsyncDriverFunction" in a sync way, where it have to wait for it to finish all its work before I process the code that follows
Be able to handle exceptions in both functions (from what I read so far this is tricky?)
I need a simple way using the standard API, I can't use any third party library (even if I wanted to)
however I'm still confused and I need a straight forward answer.
That's because there isn't a "straight-forward" answer.
The only proper solution is to make MySyncFunction asynchronous. Period. All other solutions are hacks, and there is no hack that works perfectly in all scenarios.
I go into full details in my recent MSDN article on brownfield async development, but here's the gist:
You can block with Wait() or Result. As others have noted, you can easily cause a deadlock, but this can work if the asynchronous code never resumes on its captured context.
You can push the work to a thread pool thread and then block. However, this assumes that the asynchronous work is capable of being pushed to some other arbitrary thread and that it can resume on other threads, thus possibly introducing multithreading.
You can push the work to a thread pool thread that executes a "main loop" - e.g., a dispatcher or my own AsyncContext type. This assumes the asynchronous work is capable of being pushed to another thread but removes any concerns about multithreading.
You can install a nested message loop on the main thread. This will execute the asynchronous code on the calling thread, but also introduces reentrancy, which is extremely difficult to reason about correctly.
In short, there is no one answer. Every single approach is a hack that works for different kinds of asynchronous code.
Simply calling .Result or .Wait against your async method will deadlock because you're in the context of a GUI application. See https://msdn.microsoft.com/en-us/magazine/jj991977.aspx (chapter 'Async All the Way') for a nice explanation.
The solution to your problem is not easy, but it has been described in details by Stephen Cleary: here.
So you should use the Nito.AsyncEx library (available on Nuget).
If you really can't add the library he wrote to your project, you could check the source code and use portions of it, the MIT license allows it.
Just add a .Result call at the end of the method call.
var strCollection = MyAsyncDriverFunction().Result;
I'm not sure what the experts would say, but based on the Stephen Cleary advices I end up with the following idea. Having the following class
public sealed class AsyncTask
{
public static void Run(Func<Task> asyncFunc)
{
var originalContext = SynchronizationContext.Current;
bool restoreContext = false;
try
{
if (originalContext != null && originalContext.GetType() != typeof(SynchronizationContext))
{
restoreContext = true;
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
}
var task = asyncFunc();
task.GetAwaiter().GetResult();
}
finally
{
if (restoreContext) SynchronizationContext.SetSynchronizationContext(originalContext);
}
}
public static TResult Run<TResult>(Func<Task<TResult>> asyncFunc)
{
var originalContext = SynchronizationContext.Current;
bool restoreContext = false;
try
{
if (originalContext != null && originalContext.GetType() != typeof(SynchronizationContext))
{
restoreContext = true;
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
}
var task = asyncFunc();
return task.GetAwaiter().GetResult();
}
finally
{
if (restoreContext) SynchronizationContext.SetSynchronizationContext(originalContext);
}
}
}
and use it as follows
public void MySyncFunction()
{
try
{
AsyncTask.Run(() => MyAsyncDriverFunction());
}
catch (Exception exp)
{
}
}
would do what you are asking for without deadlock. The key point is to "hide" the current synchronization context during the asynchronous task execution and force using of the default synchronization context which is known to use thread pool for Post method. Again, I'm not sure if this is good or bad idea and what side effects it could introduce, but once you asked, I'm just sharing it.
Try change "await AsyncExternalLibraryFunction1()" to "AsyncExternalLibraryFunction1().Wait()" and next to it, and remove
async for function "MyAsyncDriverFunction"
I'm getting confusing behavior when using a different SynchronizationContext inside an async function than outside.
Most of my program's code uses a custom SynchronizationContext that simply queues up the SendOrPostCallbacks and calls them at a specific known point in my main thread. I set this custom SynchronizationContext at the beginning of time and everything works fine when I only use this one.
The problem I'm running into is that I have functions that I want their await continuations to run in the thread pool.
void BeginningOfTime() {
// MyCustomContext queues each endOrPostCallback and runs them all at a known point in the main thread.
SynchronizationContext.SetSynchronizationContext( new MyCustomContext() );
// ... later on in the code, wait on something, and it should continue inside
// the main thread where MyCustomContext runs everything that it has queued
int x = await SomeOtherFunction();
WeShouldBeInTheMainThreadNow(); // ********* this should run in the main thread
}
async int SomeOtherFunction() {
// Set a null SynchronizationContext because this function wants its continuations
// to run in the thread pool.
SynchronizationContext prevContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext( null );
try {
// I want the continuation for this to be posted to a thread pool
// thread, not MyCustomContext.
await Blah();
WeShouldBeInAThreadPoolThread(); // ********* this should run in a thread pool thread
} finally {
// Restore the previous SetSynchronizationContext.
SynchronizationContext.SetSynchronizationContext( prevContext );
}
}
The behavior I'm getting is that the code right after each await is executed in a seemingly-random thread. Sometimes, WeShouldBeInTheMainThreadNow() is running in a thread pool thread and sometimes the main thread. Sometimes WeShouldBeInAThreadPoolThread() is running
I don't see a pattern here, but I thought that whatever SynchronizationContext.Current was set to at the line where you use await is the one that will define where the code following the await will execute. Is that an incorrect assumption? If so, is there a compact way to do what I'm trying to do here?
I would expect your code to work, but there are a few possible reasons why it's not:
Ensure your SynchronizationContext is current when it executes its continuations.
It's not strictly defined when the SynchronizationContext is captured.
The normal way to run code in a SynchronizationContext is to establish the current one in one method, and then run another (possibly-asynchronous) method that depends on it.
The normal way to avoid the current SynchronizationContext is to append ConfigureAwait(false) to all tasks that are awaited.
There is a common misconception about await, that somehow calling an async-implemented function is treated specially.
However, the await keyword operates on an object, it does not care at all where the awaitable object comes from.
That is, you can always rewrite await Blah(); with var blahTask = Blah(); await blahTask;
So what happens when you rewrite the outer await call that way?
// Synchronization Context leads to main thread;
Task<int> xTask = SomeOtherFunction();
// Synchronization Context has already been set
// to null by SomeOtherFunction!
int x = await xTask;
And then, there is the other issue: The finally from the inner method is executed in the continuation, meaning that it is executed on the thread pool - so not only you have unset your SynchronizationContext, but your SynchronizationContext will (potentially) be restored at some time in the future, on another thread. However, because I do not really understand the way that the SynchronizationContext is flowed, it is quite possible that the SynchronizationContext is not restored at all, that it is simply set on another thread (remember that SynchronizationContext.Current is thread-local...)
These two issues, combined, would easily explain the randomness that you observe. (That is, you are manipulating quasi-global state from multiple threads...)
The root of the issue is that the await keyword does not allow scheduling of the continuation task.
In general, you simply want to specify "It is not important for the code after the await to be on the same context as the code before await", and in that case, using ConfigureAwait(false) would be appropriate;
async Task SomeOtherFunction() {
await Blah().ConfigureAwait(false);
}
However, if you absolutely want to specify "I want the code after the await to run on the thread pool" - which is something that should be rare, then you cannot do it with await, but you can do it e.g. with ContinueWith - however, you are going to mix multiple ways of using Task objects, and that can lead to pretty confusing code.
Task SomeOtherFunction() {
return Blah()
.ContinueWith(blahTask => WeShouldBeInAThreadPoolThread(),
TaskScheduler.Default);
}
Is there a C# equivalent of F#'s StartImmediate which can be executed on a Task? I have a situation where I need to await a function sometimes, but other times I just want the method to call back to the UI thread without using await.
I want to avoid async void if possible.
Example:
public async void DoSomething()
{
//before runs on UI thread
await OtherThing();
//after runs on UI thread
}
public async Task DoSomethingElse()
{
//before runs on UI thread
await OtherThing();
//I want this to run on the UI thread
}
public void CallDoSomething()
{
DoSomething(); //no need to await, returns to the UI thread to continue execution
DoSomethingElse();//Doesn't return to the UI thread to continue execution
DoSomethingElse().???(); // how to return to the UI thread for the async callback?
}
In F# this would look like this:
let CallDoSomething () =
//more code here
async {
//runs on the current thread
do! OtherThing()
//runs on the current thread
} |> Async.StartImmediate
//code here doesn't wait for the async to finish
So, when looking at your code example. You have an async method that return a Task. You're calling that method, and then calling Start on the resulting task (without calling await). That will throw an exception at runtime. The task is already started just by calling the method. Starting an already running task (or a completed task, if it completed before it returned) will throw an exception. You can only Start a task created using the Task constructor, which you're not using.
You also claim, in comments, that you are not in the UI thread when you return after calling DoSomethingElse. That is false. The code will run in the UI thread.
You also imply that the await in DoSomethingElse won't marshal the callback to the UI thread, but it will. Since it was called from the UI thread, it captured the UI context, and uses it when calling await.
So in short, you need to do nothing except remove the call to Start.
The one problem you do have, if you structure your code like this, is that you will never know if your code errors out, as there is nothing to observe any exceptions. There are two ways you could address this. One would be for each of the methods you call in this manor to consider themselves "top level methods" and handle all exceptions instead of every throwing any.
The other option would be to store all of the tasks called in this manner and await Task.WhenAll those tasks, so you can observe any errors when they all finish.
Did you try the RunSynchronously() method of the Task class ?