I have a Windows Phone 8 app that utilizes SQLite.
I have a problem where some async SQLite operations hang indefinitely (presumably because they are awaited?)
Here is one such operation:
SQLiteAsyncConnection conn = new SQLiteAsyncConnection("myDatabase");
var query = conn.Table<MyTable>().Where(x => x.Name == "name");
var result = await query.ToListAsync();
foreach (var item in result)
{
// breakpoint in the code here is never reached
}
This is in an async method which returns a Task< string>
This method is called early from the main page code. The main page never actually builds, as the app is hanging on this method (the screen just says "Loading..." indefinitely until I stop)
I'm guessing that further up your call stack (e.g., in your main page code), you are calling Result on a Task<T>. This will deadlock your program. I explain this in detail in my Best Practices in Asynchronous Programming article and my Don't Block on Async Code blog post.
To summarize: when you await an uncompleted Task, by default the current context is captured and used to restore the remainder of the async method after the Task completes. In your case, the captured context is a UI context, which only runs on a specified thread (the UI thread).
So, your main page code calls your async method which awaits the ToListAsync operation (capturing the UI context). Your async code returns an uncompleted Task to your main page code which calls Result on it. Result will (synchronously) block until the Task completes. When the ToListAsync operation completes, it attempts to execute the rest of your async method within the captured (UI) context. But the UI thread is busy; it's blocked waiting for that Task to complete. Thus, deadlock.
Related
In the example on dart.dev the Future prints the message after the main function was done.
Why might the Future work after the main function was done? At first glance, after the completion of the main function, the entire work of the program is expected to be completed (and the Future must be cancelled).
The example code:
Future<void> fetchUserOrder() {
// Imagine that this function is fetching user info from another service or database.
return Future.delayed(Duration(seconds: 2), () => print('Large Latte'));
}
void main() {
fetchUserOrder();
print('Fetching user order...');
}
The program prints
Fetching user order...
Large Latte
I've expected just the following
Fetching user order...
This has to do with the nature of futures and asynchronous programming. Behind the scenes, Dart manages something called the asynchronous queue. When you initiate a future (either manually like you did with Future.delayed or implicitly by calling a method marked async, that function's execution goes into the queue whenever its execution gets deferred. Every cycle when Dart's main thread is idle, it checks the futures in the queue to see if any of them are no longer blocked, and if so, it resumes their execution.
A Dart program will not terminate while futures are in the queue. It will wait for all of them to either complete or error out.
I'm trying to call an asynchronous method from a synchronous method like below:
1. public List<Words> Get(string code)
{
Task<List<Words>> taskWords = GetWordsAsync(code);
var result = taskWords.Result;
return result;
}
private async Task<List<Words>> GetWordsAsync(string code)
{
var result = await codeService.GetWordsByCodeAsync(code);
return result;
}
But this lead to a deadlock, await is not getting the results from the method - GetWordsByCodeAsync
I've done a bit of research and came to know that if we are calling an async method from synchronous method we should use Task.Run
When I changed the code like below, it worked:
2. public List<Words> Get(string code)
{
Task<List<Words>> taskWords = Task.Run<List<Words>>(async () => await GetWordsAsync(code);
var result = taskWords.Result;
return result;
}
private async Task<List<Words>> GetWordsAsync(string code)
{
var result = await codeService.GetWordsByCodeAsync(code);
return result;
}
But I didn't get the context, why it caused a deadlock for 1st way and 2nd one worked fine.
I'd like to know:
What's the difference between two ways?
Is second one the correct way to call async method from synchronous method?
Will using the second method also causes a deadlock at some point of time if the result is large? or is it fail proof(safe) method to use?
Also, please suggest any best practices to better do it as I have to do 5 async calls from a synchronous method - just like taskWords, I have taskSentences etc.,
Note: I don't want to change everything to async. I want to call async method from synchronous method.
I don't want to change everything to async. I want to call async method from synchronous method.
From a technical standpoint, this doesn't make sense. Asynchronous means it doesn't block the calling thread; synchronous means it does. So you understand that if you block on asynchronous code, then it's no longer truly asynchronous? The only benefit to asynchronous code is that it doesn't block the calling thread, so if you block on the asynchronous code, you're removing all the benefit of asynchrony in the first place.
The only good answer is to go async all the way. There are some rare scenarios where that's not possible, though.
What's the difference between two ways?
The first one executes the asynchronous code directly and then blocks the calling thread, waiting for it to finish. You're running into a deadlock because the asynchronous code is attempting to resume on the calling context (which await does by default), and presumably you're running this code on a UI thread or in an ASP.NET Classic request context, which only allow one thread in the context at a time. There's already a thread in the context (the one blocking, waiting for the task to finish), so the async method cannot resume and actually finish.
The second one executes the asynchronous code on a thread pool thread and then blocks the calling thread, waiting for it to finish. There is no deadlock here because the asynchronous code resumes on its calling context, which is a thread pool context, so it just continues executing on any available thread pool thread.
Is second one the correct way to call async method from synchronous method?
There is no "correct" way to do this. There are a variety of hacks, each of which has different drawbacks, and none of which work in every situation.
Will using the second method also causes a deadlock at some point of time if the result is large? or is it fail proof(safe) method to use?
It will not deadlock. What it does, though, is execute GetWordsAsync on a thread pool thread. As long as GetWordsAsync can be run on a thread pool thread, then it will work.
Also, please suggest any best practices to better do it
I have written an article on the subject. In your case, if GetWordsAsync is safe to call on a thread pool thread, then the "blocking thread pool hack" is acceptable.
Note that this is not the best solution; the best solution is to go async all the way. But the blocking thread pool hack is an acceptable hack if you must call asynchronous code from synchronous code (again, it's "acceptable" only if GetWordsAsync is safe to call on a thread pool thread).
I would recommend using GetAwaiter().GetResult() rather than Result, in order to avoid the AggregateException wrapper on error. Also, the explicit type arguments are unnecessary, and you can elide async/await in this case:
var taskWords = Task.Run(() => GetWordsAsync(code));
return taskWords.GetAwaiter().GetResult();
I have some async services that I would like to call in different places in Xamarin application. I port my code from native UWP app with Prism.
Some time ago I was able to do this by declaring making methods like
protected override void OnInitialized()
or
public override async void OnNavigatedTo(NavigationParameters parameters)
used await there. However, it stopped working.
Trying to use GetAwaiter().GetResult() blocks execution and results in deadlock.
This is kind of weird, considering that INavigationService.NavigateAsync itself is async method, but samples suggest to use in OnInitialized without any await, which I believe is wrong.
So, does anyone have a suggestion how to proper make async calls in Prism.Forms?
OnNavigatedTo gets called from the UI thread (it is part of the UI Lifecycle). If you block inside that method, you will of course have a deadlock.
Just because NavigateAsync returns a Task and has an async name, doesn't mean everything in that method happens on another thread. It just means it usually does something, that you could wait for.
The problem here is, that OnNavigatedTo is returning void, so it will return to the caller, once you have an await in there. That doesn't stop you from using it, you just cant block there.
public override async void OnNavigatedTo(NavigationParameters parameters)
{
// do sync stuff
await DoSomethingAsync();
// this happens after all the other lifecycle methods
}
Just be aware, that everything after the await just happens after the whole navigation is done. And that exceptions thrown in there will not show up (it's basically fire and forget).
You can always make the continuation explicit by not using async/await and using .ContinueWith(...) instead.
I am creating a piece of code that gets a webpage from a legacy system we have. In order to avoid excessive querying, I am caching the obtained URL. I am using Monitor.Enter, Monitor.Exit and double checking to avoid that request is issued twice, but when releasing the lock with Monitor.Exit, I am getting this exception:
System.Threading.SynchronizationLockException was caught
HResult=-2146233064
Message=Object synchronization method was called from an unsynchronized block of code.
Source=MyApp
StackTrace:
at MyApp.Data.ExProvider.<OpenFeature>d__0.MoveNext() in c:\Users\me\Documents\Visual Studio 2013\Projects\MyApp\MyApp\Data\ExProvider.cs:line 56
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MyApp.Data.ExProvider.<GetSupportFor>d__15.MoveNext() in c:\Users\me\Documents\Visual Studio 2013\Projects\MyApp\MyApp\Data\ExProvider.cs:line 71
InnerException:
The line 56 is the Monitor.Exit. This is the code that performs the operation:
private async Task<Stream> OpenReport(String report)
{
var file = _directory.GetFiles(report+ ".html");
if (file != null && file.Any())
return file[0].OpenRead();
else
{
try
{
Monitor.Enter(_locker);
FileInfo newFile = new FileInfo(Path.Combine(_directory.FullName, report + ".html"));
if (!newFile.Exists) // Double check
{
using (var target = newFile.OpenWrite())
{
WebRequest request = WebRequest.Create(BuildUrl(report));
var response = await request.GetResponseAsync();
using (var source = response.GetResponseStream())
source.CopyTo(target);
}
}
return newFile.OpenRead();
}
finally
{
Monitor.Exit(_locker);
}
}
}
So what is the problem with await and Monitor? Is it because it is not the same thread when Monitor.Enter than when Monitor.Exit?
You can't await a task inside a lock scope (which is syntactic sugar for Monitor.Enter and Monitor.Exit). Using a Monitor directly will fool the compiler but not the framework.
async-await has no thread-affinity like a Monitor does. The code after the await will probably run in a different thread than the code before it. Which means that the thread that releases the Monitor isn't necessarily the one that acquired it.
Either don't use async-await in this case, or use a different synchronization construct like SemaphoreSlim or an AsyncLock you can build yourself. Here's mine: https://stackoverflow.com/a/21011273/885318
In SendRequest however, I need to 'await', and thus I'm unable to use lock for some reason I didn't give much thought, so the solution to synchronize is to use Monitor.
Should have given it more thought. :)
There are two problems with using blocking locks with async code.
The first problem is that - in the general case - an async method may resume executing on a different thread. Most blocking locks are thread-affine, meaning that they must be released from the thread that owns them (the same thread that acquired the lock). It is this violation of Monitor thread-affinity that causes the SynchronizationLockException. This problem does not happen if the await captures an execution context (e.g., a UI context) and used that to resume the async method (e.g., on the UI thread). Or if you just got lucky and the async method happened to resume on the same thread pool thread.
However, even if you avoid the first problem, you still have a second problem: any arbitrary code can execute while an async method is "paused" at an await point. This is a violation of a cardinal rule of locking ("do not execute arbitrary code while holding a lock"). For example, thread-affine locks (including Monitor) are generally re-entrant, so even in the UI thread scenario, when your async method is "paused" (and holding the lock), other methods running on the UI thread can take the lock without any problems.
On Windows Phone 8, use SemaphoreSlim instead. This is a type that allows both blocking and asynchronous coordination. Use Wait for a blocking lock and WaitAsync for an asynchronous lock.
I am making some probes with async CTP but I don't get a good result, because the GUI is blocked.
I have an WPF application with a button and a textBox for a log. Then I have this code:
private async void btnAsync01_Click(object sender, RoutedEventArgs e)
{
UpdateTxtLog("Enter in Button Async01: " + System.DateTime.Now);
await metodo01Async();
UpdateTxtLog("Exit button Async01: " + System.DateTime.Now);
}
private async Task slowMethodAsync()
{
UpdateTxtLog("Enter in slowMethod: " + System.DateTime.Now);
Thread.Sleep(5000);
UpdateTxtLog("Exit slowMethod: " + System.DateTime.Now);
}
If am not wrong, set a method with "sync" (click event in this case), it let the method use the await, to return the point to execution to the method which call the actual method, then the execution return to the GUI.
So in the GUI,I click the button, then in the click event await to the slowMethod, how I use await with the slowMethod the control should be returned to the GUI, and then the GUI should not be blocked. However, the GUI is blocked and the txtLog not show any information until slowMethod finish.
Is this because slowMethod is executed in the same thread than the GUI? If I am wrong, with async normally use the same thread than the method which call the await method, but I think that the reason of the async avoid this.
How can I simulate an slowMethod without thread.Sleep? Perhaps this is the problem, because in slowMethod I sleep the thread, and the thread of slowMethod is the same than the GUI.
This makes me think that is always recommended execute in other thread the code of the async methods? If this is correct, which is the sense to use async if also I need to use task for not blocking the main thread?
When to use async and when to use tasks?
For this probes, I am following the examples in this web: http://www.codeproject.com/Articles/127291/C-5-0-vNext-New-Asynchronous-Pattern
In this example, it's used client.DownloadStringTaskAsync as slowMethod, but in my case, instead of using a WebClient, I use a dummy method, with a sleep to simulate a slowMethod. I think that is the unique difference.
Thanks.
Daimroc.
Simulate waits using await TaskEx.Delay(5000), which executes an asynchronous sleep/delay.
You may also want to read up some more on async/await. There are several good Channel9 videos; Stephen Toub, Eric Lippert, and many other Microsoft bloggers have excellent overviews. Jon Skeet's "eduasync" blog series is also good for really going deep. I've written up an async intro on my own blog, as have many others.
Here's how async and await really work, in a nutshell:
The async keyword only enables the await keyword. That is all. It does not run the method on a background thread.
await only acts asynchronously if its "awaiter" is not completed.
So in your case, btnAsync01_Click and slowMethodAsync both run on the UI thread. slowMethodAsync will run synchronously (executing Thread.Sleep), and then return to btnAsync01_Click, which awaits the already-completed task. Since the task is already completed, btnAsync01_Click just continues executing without yielding to the UI message loop.
If you replace Thread.Sleep with await TaskEx.Delay, then btnAsync01_Click will start running on the UI thread, and will call slowMethodAsync (also running on the UI thread). When slowMethodAsync awaits the delay (which is not completed), it will return an incomplete task to btnAsync01_Click. btnAsync01_Click will await that task (which is not completed), and will return to the UI loop.
When the delay expires, it will complete, and slowMethodAsync will resume (on the UI thread). When slowMethodAsync completes, its returned task will complete, and btnAsync01_Click will resume (on the UI thread).