Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a WPF app with an EF connection to a database. But when I call await DbSet().SingleAsync() my UI thread is stuck and not responsive. I figured out that when I ran await it will still run on main UI thread so I can access UI. That will explain why it is working when I use only Task.Delay(), because SingleAsync is using thread, but Task.Delay() doesn't.
ConfigureAwait(false) should solve this and run it on different thread. But it doesn't and my UI still freeze.
Am I doing it wrong ?
Code:
private async void Button_Login_Click(object sender, RoutedEventArgs e)
{
await userService.ValidateCredentials(textBoxLogin.Text, textBoxLogin.Text).ConfigureAwait(false);
}
public async Task<bool> ValidateCredentials(string username, string password)
{
User user = await userDao.SingleOrNull(true, o => o.Username == username && o.Password == password);
if (user == null)
return (false);
return (true);
}
public async Task<ResourceDbType> SingleOrNull(bool noTracking, Expression<Func<ResourceDbType, bool>> where)
{
ResourceDbType ret;
try
{
if (noTracking)
{
ret = await GetDbSet().AsNoTracking().SingleAsync(where);
}
else
ret = await GetDbSet().SingleAsync(where);
}
catch (Exception ex)
{
return null;
}
return ret;
}
EDIT:
BaseDao should only expose functions from DbContext with selected DbSet model registered at MainDbContext. We are using this code at work at RestApi service, so I reused it because I am used to it.
[RegisterClass(Lifetime.Scoped)] is atribute for marking class to Register it in DependencyInjection at start of app with reflection.
Dao code:
public class BaseDao<ResourceDbType> : IDisposable where ResourceDbType : class, new()
{
public DbContext DbContext { get; protected set; }
public BaseDao(MainDbContext mainDbContext)
{
DbContext = mainDbContext;
}
public DbSet<ResourceDbType> GetDbSet()
{
return this.DbContext.Set<ResourceDbType>();
}
public List<ResourceDbType> ToList()
{
return this.GetDbSet().ToList();
}
public ResourceDbType[] ToArray()
{
return this.GetDbSet().ToArray();
}
public async Task<ResourceDbType> SingleOrNull(bool noTracking, Expression<Func<ResourceDbType, bool>> where)
{
ResourceDbType ret;
try
{
if (noTracking)
{
ret = await GetDbSet().AsNoTracking().SingleAsync(where);
}
else
ret = await GetDbSet().SingleAsync(where);
}
catch (Exception ex)
{
return null;
}
return ret;
}
public void Dispose()
{
this.DbContext?.Dispose();
}
}
UserDao Code:
[RegisterClass(Lifetime.Scoped)]
public class UserDao : BaseDao<User>
{
public UserDao(MainDbContext mainDbContext) : base(mainDbContext)
{
}
}
Async is not a silver bullet, and from what I see from the example, it is most likely unnecessary. Async is not ideal for "use everywhere, every time" but rather for potentially mitigating expensive operations.
By tucking away EF behind a service and then a repository makes your EF operations a lot less efficient than they could be.
For example: Without a repository level. (Trust EF to be used by the service, and injected into the service)
// UI
private void Button_Login_Click(object sender, RoutedEventArgs e)
{
var result = userService.ValidateCredentials(textBoxLogin.Text, textBoxLogin.Text);
}
// Service
public bool ValidateCredentials(string username, string password)
{
var result = Context.Users.Any(x => x.UserName == userName && x.Password == password);
return result;
}
EF can generate a very efficient EXISTS query rather than loading an entity just to check if a row exists. Faster code without needing to worry about handing it off.
If you want to be able to unit test the service, then you can introduce a repository. I recommend leveraging IQueryable:
// Service
public bool ValidateCredentials(string username, string password)
{
using (var unitOfWork = UnitOfWorkFactory.Create())
{
var result = UserRepository.FindUserByName(username, password).Any();
return result;
}
}
// Repository
public IQueryable<User> FindUserByName(string userName, string password)
{
var query = Context.Users.Where(x => x.UserName == userName && x.Password == password);
return query;
}
The repository can guard access to the Entities to ensure required rules are followed etc. yet can be more easily mocked out than the DbContext. This requires consideration for scoping the DbContext in a Unit of Work to facilitate the Service to control the boundary of the DbContext and interact with the resulting entities returned by the Repository. The implementation I use for that with EF is Medhime's DbContextScope. (There are forks available for EF Core) This gives the service full control over how the entities are consumed with the repository enforcing the rules and making mocking simpler.
Side Note: Some devs don't like that the services need to be aware of EF concerns (such as legal Lambdas that EF can understand) but this is a trade off for a thinner, much more flexible Repository. (Handling additional criteria, projection, sorting, paging, etc. is a snap however a particular consumer needs.) I've seen many attempts to abstract away EF to accept criteria, sorting, projection, and paging into repository methods using Func etc. but the reality is that these are quite complex and still have to adhere to EF's rules anyways. Ultimately when you choose to use EF you need to trust it as part of your solution in order to leverage it to it's fullest.
Async is geared more towards particularly expensive operations. WPF's synchronization context essentially supports interacting with async code, but since this is going to ensure code resumes on the UI thread, there is arguably little benefit using it other than facilitating it to be able to await async methods. This is more to facilitate an event handler to work properly when calling and awaiting several async operations.
I.e.
private async void Button_Login_Click(object sender, RoutedEventArgs e)
{
var firstTask = userService.DoSomethingThatMightTake5SecondsAsync(); // Don't actually name your tasks this! :)
var secondTask = userService.DoSomethingThatMightTake5SecondsAsync();
var thirdTask = userService.DoSomethingThatMightTake5SecondsAsync();
// Do stuff that doesn't rely on those 3 tasks....
var firstResult = await firstTask;
// Do something with first task results
var secondResult = await secondTask;
// Do something with second task results
var thirdResult = await thirdTask;
// Do something with third task results
}
Synchronously, those 3 operations would take 15 seconds and whatever else needs to happen that doesn't rely on them would have to wait until they complete. Asynchronously they could complete faster, and independent code could execute while they are processing.
Though caution would be needed in the above example with EF as things like the DbContext is not thread safe so kicking off 3 async methods that result in the use of a single DbContext would result in calls to the DbContext by multiple threads. Awaiting them in turn with a UI Thread Sync context is effectively the same as sync calls, only marginally slower. (Overhead of spawning the thread pool threads and waiting for the sync context)
Using async should be situational.
Edit: Example with Async vs. Sync:
With a simple WPF form with 2 buttons and a text box (uxEntry). One button for a Synchronous event, one with an Asynchronous event. The textbox will receive focus after one of the buttons is called and you can try typing in it to see if the UI thread is responding:
private async void AsyncButton_Click(object sender, RoutedEventArgs e)
{
uxEntry.Focus();
var result = await DoSomethingAsync();
MessageBox.Show(result);
}
private void SyncButton_Click(object sender, RoutedEventArgs e)
{
uxEntry.Focus();
var result = DoSomethingSync();
MessageBox.Show(result);
}
private async Task<string> DoSomethingAsync()
{
await Task.Run(() =>
{
Thread.Sleep(5000);
});
return "Done";
}
private string DoSomethingSync()
{
Thread.Sleep(5000);
return "Done";
}
In the case where you click the Sync button, the text box won't receive focus or accept input until the 5 seconds is up. In the Async example, it will respond immediately while the async task is running. Async events allow the UI thread to continue responding to events which can make your app feel more responsive, however combining this with EF DbContexts, which are not thread safe, can lead to issues.
Using Async to parallelize operations would be dangerous with code using a single injected DbContext reference, for example:
private async void AsyncMultiButton_Click(object sender, RoutedEventArgs e)
{
uxEntry.Focus();
var task1 = DoSomethingAsync();
var task2 = DoSomethingAsync();
var task3 = DoSomethingAsync();
var result1 = await task1;
var result2 = await task2;
var result3 = await task3;
var message = string.Format("Task1: {0} Task2: {1} Task3: {2}", result1, result2, result3);
MessageBox.Show(message);
}
If DoSomethingAsync talked to a repository DbContext those 3 tasks would all start simultaneously, and the DbContext will not like that. Depending on the code it can lead to headaches as it appears to work sometimes or in debug environments only to crash with errors at others or in production. The solution would be to await each one in turn:
uxEntry.Focus();
var result1 = await DoSomethingAsync();
var result2 = await DoSomethingAsync();
var result3 = await DoSomethingAsync();
This would be safe for the DbContext, and the UI would be responsive, however that would now take 15 seconds to complete. It can be tempting to kick them off in parallel, just something to be cautious of when using async. It can be useful for making your application appear more responsive, but be cautious when thinking it can make your application "faster".
Looking at your original code example I don't see a glaring reason why the awaited event handler would still appear to lock up the UI, though that may be some difference between your current code and the example you provided.
Related
I've been working on a project and saw the below code. I am new to the async/await world. As far as I know, only a single task is performing in the method then why it is decorated with async/await. What benefits I am getting by using async/await and what is the drawback if I remove async/await i.e make it synchronous I am a little bit confused so any help will be appreciated.
[Route("UpdatePersonalInformation")]
public async Task<DataTransferObject<bool>> UpdatePersonalInformation([FromBody] UserPersonalInformationRequestModel model)
{
DataTransferObject<bool> transfer = new DataTransferObject<bool>();
try
{
model.UserId = UserIdentity;
transfer = await _userService.UpdateUserPersonalInformation(model);
}
catch (Exception ex)
{
transfer.TransactionStatusCode = 500;
transfer.ErrorMessage = ex.Message;
}
return transfer;
}
Service code
public async Task<DataTransferObject<bool>> UpdateUserPersonalInformation(UserPersonalInformationRequestModel model)
{
DataTransferObject<bool> transfer = new DataTransferObject<bool>();
await Task.Run(() =>
{
try
{
var data = _userProfileRepository.FindBy(x => x.AspNetUserId == model.UserId)?.FirstOrDefault();
if (data != null)
{
var userProfile = mapper.Map<UserProfile>(model);
userProfile.UpdatedBy = model.UserId;
userProfile.UpdateOn = DateTime.UtcNow;
userProfile.CreatedBy = data.CreatedBy;
userProfile.CreatedOn = data.CreatedOn;
userProfile.Id = data.Id;
userProfile.TypeId = data.TypeId;
userProfile.AspNetUserId = data.AspNetUserId;
userProfile.ProfileStatus = data.ProfileStatus;
userProfile.MemberSince = DateTime.UtcNow;
if(userProfile.DOB==DateTime.MinValue)
{
userProfile.DOB = null;
}
_userProfileRepository.Update(userProfile);
transfer.Value = true;
}
else
{
transfer.Value = false;
transfer.Message = "Invalid User";
}
}
catch (Exception ex)
{
transfer.ErrorMessage = ex.Message;
}
});
return transfer;
}
What benefits I am getting by using async/await
Normally, on ASP.NET, the benefit of async is that your server is more scalable - i.e., can handle more requests than it otherwise could. The "Synchronous vs. Asynchronous Request Handling" section of this article goes into more detail, but the short explanation is that async/await frees up a thread so that it can handle other requests while the asynchronous work is being done.
However, in this specific case, that's not actually what's going on. Using async/await in ASP.NET is good and proper, but using Task.Run on ASP.NET is not. Because what happens with Task.Run is that another thread is used to run the delegate within UpdateUserPersonalInformation. So this isn't asynchronous; it's just synchronous code running on a background thread. UpdateUserPersonalInformation will take another thread pool thread to run its synchronous repository call and then yield the request thread by using await. So it's just doing a thread switch for no benefit at all.
A proper implementation would make the repository asynchronous first, and then UpdateUserPersonalInformation can be implemented without Task.Run at all:
public async Task<DataTransferObject<bool>> UpdateUserPersonalInformation(UserPersonalInformationRequestModel model)
{
DataTransferObject<bool> transfer = new DataTransferObject<bool>();
try
{
var data = _userProfileRepository.FindBy(x => x.AspNetUserId == model.UserId)?.FirstOrDefault();
if (data != null)
{
...
await _userProfileRepository.UpdateAsync(userProfile);
transfer.Value = true;
}
else
{
transfer.Value = false;
transfer.Message = "Invalid User";
}
}
catch (Exception ex)
{
transfer.ErrorMessage = ex.Message;
}
return transfer;
}
The await keyword only indicates that the execution of the current function is halted until the Task which is being awaited is completed. This means if you remove the async, the method will continue execution and therefore immediately return the transfer object, even if the UpdateUserPersonalInformation Task is not finished.
Take a look at this example:
private void showInfo()
{
Task.Delay(1000);
MessageBox.Show("Info");
}
private async void showInfoAsync()
{
await Task.Delay(1000);
MessageBox.Show("Info");
}
In the first method, the MessageBox is immediately displayed, since the newly created Task (which only waits a specified amount of time) is not awaited. However, the second method specifies the await keyword, therefore the MessageBox is displayed only after the Task is finished (in the example, after 1000ms elapsed).
But, in both cases the delay Task is ran asynchronously in the background, so the main thread (for example the UI) will not freeze.
The usage of async-await mechanism mainly used
when you have some long calculation process which takes some time and you want it to be on the background
in UI when you don't want to make the main thread stuck which will be reflected on UI performance.
you can read more here:
https://learn.microsoft.com/en-us/dotnet/csharp/async
Time Outs
The main usages of async and await operates preventing TimeOuts by waiting for long operations to complete. However, there is another less known, but very powerful one.
If you don't await long operation, you will get a result back, such as a null, even though the actual request as not completed yet.
Cancellation Tokens
Async requests have a default parameter you can add:
public async Task<DataTransferObject<bool>> UpdatePersonalInformation(
[FromBody] UserPersonalInformationRequestModel model,
CancellationToken cancellationToken){..}
A CancellationToken allows the request to stop when the user changes pages or interrupts the connection. A good example of this is a user has a search box, and every time a letter is typed you filter and search results from your API. Now imagine the user types a very long string with say 15 characters. That means that 15 requests are sent and 15 requests need to be completed. Even if the front end is not awaiting the first 14 results, the API is still doing all the 15 requests.
A cancellation token simply tells the API to drop the unused threads.
I would like to chime in on this because most answers although good, do not point to a definite time when to use and when not.
From my experience, if you are developing anything with a front-end, add async/await to your methods when expecting output from other threads to be input to your UI. This is the best strategy for handling multithread output and Microsoft should be commended to come out with this when they did. Without async/await you would have to add more code to handle thread output to UI (e.g Event, Event Handler, Delegate, Event Subscription, Marshaller).
Don't need it anywhere else except if using strategically for slow peripherals.
Suppose I have written a library which relies on async methods:
namespace MyLibrary1
{
public class ClassFromMyLibrary1
{
public async Task<string> MethodFromMyLibrary1(string key, Func<string, Task<string>> actionToProcessNewValue)
{
var remoteValue = await GetValueByKey(key).ConfigureAwait(false);
//do some transformations of the value
var newValue = string.Format("Remote-{0}", remoteValue);
var processedValue = await actionToProcessNewValue(newValue).ConfigureAwait(false);
return string.Format("Processed-{0}", processedValue);
}
private async Task<string> GetValueByKey(string key)
{
//simulate time-consuming operation
await Task.Delay(500).ConfigureAwait(false);
return string.Format("ValueFromRemoteLocationBy{0}", key);
}
}
}
I followed the recommendations of using ConfigureAwait(false) (like in this post) everywhere in my library. Then I use it in synchronous way from my test app and get a failure:
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button1_OnClick(object sender, RoutedEventArgs e)
{
try
{
var c = new ClassFromMyLibrary1();
var v1 = c.MethodFromMyLibrary1("test1", ActionToProcessNewValue).Result;
Label2.Content = v1;
}
catch (Exception ex)
{
System.Diagnostics.Trace.TraceError("{0}", ex);
throw;
}
}
private Task<string> ActionToProcessNewValue(string s)
{
Label1.Content = s;
return Task.FromResult(string.Format("test2{0}", s));
}
}
}
The failure is:
WpfApplication1.vshost.exe Error: 0 :
System.InvalidOperationException: The calling thread cannot access
this object because a different thread owns it. at
System.Windows.Threading.Dispatcher.VerifyAccess() at
System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object
value) at System.Windows.Controls.ContentControl.set_Content(Object
value) at WpfApplication1.MainWindow.ActionToProcessNewValue(String
s) in
C:\dev\tests\4\WpfApplication1\WpfApplication1\MainWindow.xaml.cs:line
56 at
MyLibrary1.ClassFromMyLibrary1.d__0.MoveNext()
in
C:\dev\tests\4\WpfApplication1\WpfApplication1\MainWindow.xaml.cs:line
77
--- 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 WpfApplication1.MainWindow.d__1.MoveNext() in
C:\dev\tests\4\WpfApplication1\WpfApplication1\MainWindow.xaml.cs:line
39 Exception thrown: 'System.InvalidOperationException' in
WpfApplication1.exe
Obviously the error happens because the awaiters in my library discard current WPF context.
From the other hand, after removing the ConfigureAwait(false) everywhere in the library I obviously get a deadlock instead.
There is more detailed example of code which explains some constraints that I have to deal with.
So how can I address this issue? What is the best approach here? Do I still need to follow the best practice regarding ConfigureAwait?
PS, In real scenario I have many classes and methods therefore tons of such async calls in my library. It's nearly impossible to find out if some particular async call requires context or not (see comments to #Alisson response) to fix it. I don't care about performance though, at least at this point. I'm looking for some general approach to address this issue.
Normally a library will document if a callback will be guaranteed to be on the same thread that called it, if it is not documented the safest option will be to assume it does not. Your code example (and the 3rd party you are working with from what I can tell from your comments) fall under the category of "Not guaranteed". In that situation you just need to check if you need to do a Invoke from inside the callback method and do it, you can call Dispatcher.CheckAccess() and it will return false if you need to invoke before using the control.
private async Task<string> ActionToProcessNewValue(string s)
{
//I like to put the work in a delegate so you don't need to type
// the same code for both if checks
Action work = () => Label1.Content = s;
if(Label1.Dispatcher.CheckAccess())
{
work();
}
else
{
var operation = Label1.Dispatcher.InvokeAsync(work, DispatcherPriority.Send);
//We likely don't need .ConfigureAwait(false) because we just proved
// we are not on the UI thread in the if check.
await operation.Task.ConfigureAwait(false);
}
return string.Format("test2{0}", s);
}
Here is a alternate version with a syncronous callback instead of a async one.
private string ActionToProcessNewValue(string s)
{
Action work = () => Label1.Content = s;
if(Label1.Dispatcher.CheckAccess())
{
work();
}
else
{
Label1.Dispatcher.Invoke(work, DispatcherPriority.Send);
}
return string.Format("test2{0}", s);
}
Here is another version if you wanted to get the value from Label1.Content instead of assigning it, this also does not need to use async/await inside the callback.
private Task<string> ActionToProcessNewValue(string s)
{
Func<string> work = () => Label1.Content.ToString();
if(Label1.Dispatcher.CheckAccess())
{
return Task.FromResult(work());
}
else
{
return Label1.Dispatcher.InvokeAsync(work, DispatcherPriority.Send).Task;
}
}
IMPORTANT NOTE: all of these methods will cause your program to deadlock if you don't get rid of the .Result in the button click handler, the Dispatcher.Invoke or the Dispatcher.InvokeAsync in the callback will never start while it is waiting for .Result to return and .Result will never return while it is waiting for the callback to return. You must change the click handler to be async void and do a await instead of the .Result.
Actually, you're receiving a callback in your ClassFromMyLibrary1 and you can't assume what it'll do (like updating a Label). You don't need ConfigureAwait(false) in your class library, as the same link you provided gives us an explanation like this:
As asynchronous GUI applications grow larger, you might find many
small parts of async methods all using the GUI thread as their
context. This can cause sluggishness as responsiveness suffers from
"thousands of paper cuts".
To mitigate this, await the result of ConfigureAwait whenever you can.
By using ConfigureAwait, you enable a small amount of parallelism:
Some asynchronous code can run in parallel with the GUI thread instead
of constantly badgering it with bits of work to do.
Now take a read here:
You should not use ConfigureAwait when you have code after the await
in the method that needs the context. For GUI apps, this includes any
code that manipulates GUI elements, writes data-bound properties or
depends on a GUI-specific type such as Dispatcher/CoreDispatcher.
You're doing exactly the opposite. You're trying to update GUI in two points, one in your callback method, and another here:
var c = new ClassFromMyLibrary1();
var v1 = c.MethodFromMyLibrary1("test1", ActionToProcessNewValue).Result;
Label2.Content = v1; // updating GUI...
That's why removing ConfigureAwait(false) solves your problem. Also, you can make your button click handler async and await your ClassFromMyLibrary1 method call.
In my opinion, you should redesign your library API to not mix a callback-based API with a Task-based API. At least in your example code there's no compelling case to be made to do that and you've nailed one reason not do do that - it is hard to control the context in which your callback runs.
I'd change your library API to be like so:
namespace MyLibrary1
{
public class ClassFromMyLibrary1
{
public async Task<string> MethodFromMyLibrary1(string key)
{
var remoteValue = await GetValueByKey(key).ConfigureAwait(false);
return remoteValue;
}
public string TransformProcessedValue(string processedValue)
{
return string.Format("Processed-{0}", processedValue);
}
private async Task<string> GetValueByKey(string key)
{
//simulate time-consuming operation
await Task.Delay(500).ConfigureAwait(false);
return string.Format("ValueFromRemoteLocationBy{0}", key);
}
}
}
And call it like so:
private async void Button1_OnClick(object sender, RoutedEventArgs e)
{
try
{
var c = new ClassFromMyLibrary1();
var v1 = await c.MethodFromMyLibrary1("test1");
var v2 = await ActionToProcessNewValue(v1);
var v3 = c.TransformProcessedValue(v2);
Label2.Content = v3;
}
catch (Exception ex)
{
System.Diagnostics.Trace.TraceError("{0}", ex);
throw;
}
}
private Task<string> ActionToProcessNewValue(string s)
{
Label1.Content = s;
return Task.FromResult(string.Format("test2{0}", s));
}
This is for an iOS app written in Xamarin. All my application code runs in the main thread (i.e. the UI thread).
The UI code does something as follows:
public async void ButtonClicked()
{
StartSpinner();
var data = await UpdateData();
StopSpinner();
UpdateScreen(data);
}
The UpdateData function does something as follows:
public Task<Data> UpdateData()
{
var data = await FetchFromServer();
TriggerCacheUpdate();
return data;
}
TriggerCacheUpdate ends up calling the following function defined below
public Task RefreshCache()
{
var data = await FetchMoreDataFromServer();
UpdateInternalDataStructures();
}
My question is how should TriggerCacheUpdate be written? The requirements are:
Can't be async, I don't want UpdateData and consequently
ButtonClicked to wait for RefreshCache to complete before
continuing.
UpdateInternalDataStructures needs to execute on the main (UI) thread, i.e. the thread that all the other code shown above executes on.
Here are a few alternatives I came up with:
public void TriggerCacheUpdate()
{
RefreshCache();
}
The above works but generates a compiler warning. Moreover exception handling from RefreshCache doesn't work.
public void TriggerCacheUpdate()
{
Task.Run(async() =>
{
await RefreshCache();
});
}
The above violates requirement 2 as UpdateInternalDataStructures is not executed on the same thread as everything else.
A possible alternative that I believe works is:
private event EventHandler Done;
public void TriggerCacheUpdate()
{
this.task = RefreshCache();
Done += async(sender, e) => await this.task;
}
Task RefreshCache() {
var data = await FetchMoreDataFromServer();
UpdateInternalDataStructures();
if (Done != null) {
Done(this, EventArgs.Empty);
}
}
Does the above work? I haven't ran into any problems thus far with my limited testing. Is there a better way to write TriggerCacheUpdate?
It's hard to say without being able to test it but it looks like your trigger cache update method is fine, it's your RefreshCache that needs to change. Inside of RefreshCache you are not waiting in the UI thread for the result of "data" to return so set the ConfigureAwait to false.
public async Task RefreshCache()
{
var data = await FetchMoreDataFromServer().ConfigureAwait(false);
UpdateInternalDataStructures();
}
Your event handler is async. That means, that even if you await for a Task to complete, that your UI remains responsive. So even if you would await for the TriggerCacheUpdate to return, your UI would remain responsive.
However, if you are really certain that you are not interested in the result of TriggerCachUpdate, then you could start a Task without waiting for it:
public Task<Data> UpdateData()
{
var data = await FetchFromServer();
Task.Run( () => TriggerCacheUpdate());
return data;
}
Note: careful: you don't know when TriggerCachUpdate is finished, not even if it ended successfully or threw an exception. Also: check what happens if you start a new TriggerCacheUpdate task while the previous one is not finished yet.
For those who want to use Task.Factory.StartNew, see the discussion about it in MSDN:
Task.Run vs Task.Factory.StartNew
It's recommended that one use ConfigureAwait(false) whenever when you can, especially in libraries because it can help avoid deadlocks and improve performance.
I have written a library that makes heavy use of async (accesses web services for a DB). The users of the library were getting a deadlock and after much painful debugging and tinkering I tracked it down to the single use of await Task.Yield(). Everywhere else that I have an await, I use .ConfigureAwait(false), however that is not supported on Task.Yield().
What is the recommended solution for situations where one needs the equivalent of Task.Yield().ConfigureAwait(false)?
I've read about how there was a SwitchTo method that was removed. I can see why that could be dangerous, but why is there no equivalent of Task.Yield().ConfigureAwait(false)?
Edit:
To provide further context for my question, here is some code. I am implementing an open source library for accessing DynamoDB (a distributed database as a service from AWS) that supports async. A number of operations return IAsyncEnumerable<T> as provided by the IX-Async library. That library doesn't provide a good way of generating async enumerables from data sources that provide rows in "chunks" i.e. each async request returns many items. So I have my own generic type for this. The library supports a read ahead option allowing the user to specify how much data should be requested ahead of when it is actually needed by a call to MoveNext().
Basically, how this works is that I make requests for chunks by calling GetMore() and passing along state between these. I put those tasks in a chunks queue and dequeue them and turn them into actual results that I put in a separate queue. The NextChunk() method is the issue here. Depending on the value of ReadAhead I will keeping getting the next chunk as soon as the last one is done (All) or not until a value is needed but not available (None) or only get the next chunk beyond the values that are currently being used (Some). Because of that, getting the next chunk should run in parallel/not block getting the next value. The enumerator code for this is:
private class ChunkedAsyncEnumerator<TState, TResult> : IAsyncEnumerator<TResult>
{
private readonly ChunkedAsyncEnumerable<TState, TResult> enumerable;
private readonly ConcurrentQueue<Task<TState>> chunks = new ConcurrentQueue<Task<TState>>();
private readonly Queue<TResult> results = new Queue<TResult>();
private CancellationTokenSource cts = new CancellationTokenSource();
private TState lastState;
private TResult current;
private bool complete; // whether we have reached the end
public ChunkedAsyncEnumerator(ChunkedAsyncEnumerable<TState, TResult> enumerable, TState initialState)
{
this.enumerable = enumerable;
lastState = initialState;
if(enumerable.ReadAhead != ReadAhead.None)
chunks.Enqueue(NextChunk(initialState));
}
private async Task<TState> NextChunk(TState state, CancellationToken? cancellationToken = null)
{
await Task.Yield(); // ** causes deadlock
var nextState = await enumerable.GetMore(state, cancellationToken ?? cts.Token).ConfigureAwait(false);
if(enumerable.ReadAhead == ReadAhead.All && !enumerable.IsComplete(nextState))
chunks.Enqueue(NextChunk(nextState)); // This is a read ahead, so it shouldn't be tied to our token
return nextState;
}
public Task<bool> MoveNext(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if(results.Count > 0)
{
current = results.Dequeue();
return TaskConstants.True;
}
return complete ? TaskConstants.False : MoveNextAsync(cancellationToken);
}
private async Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
Task<TState> nextStateTask;
if(chunks.TryDequeue(out nextStateTask))
lastState = await nextStateTask.WithCancellation(cancellationToken).ConfigureAwait(false);
else
lastState = await NextChunk(lastState, cancellationToken).ConfigureAwait(false);
complete = enumerable.IsComplete(lastState);
foreach(var result in enumerable.GetResults(lastState))
results.Enqueue(result);
if(!complete && enumerable.ReadAhead == ReadAhead.Some)
chunks.Enqueue(NextChunk(lastState)); // This is a read ahead, so it shouldn't be tied to our token
return await MoveNext(cancellationToken).ConfigureAwait(false);
}
public TResult Current { get { return current; } }
// Dispose() implementation omitted
}
I make no claim this code is perfect. Sorry it is so long, wasn't sure how to simplify. The important part is the NextChunk method and the call to Task.Yield(). This functionality is used through a static construction method:
internal static class AsyncEnumerableEx
{
public static IAsyncEnumerable<TResult> GenerateChunked<TState, TResult>(
TState initialState,
Func<TState, CancellationToken, Task<TState>> getMore,
Func<TState, IEnumerable<TResult>> getResults,
Func<TState, bool> isComplete,
ReadAhead readAhead = ReadAhead.None)
{ ... }
}
The exact equivalent of Task.Yield().ConfigureAwait(false) (which doesn't exist since ConfigureAwait is a method on Task and Task.Yield returns a custom awaitable) is simply using Task.Factory.StartNew with CancellationToken.None, TaskCreationOptions.PreferFairness and TaskScheduler.Current. In most cases however, Task.Run (which uses the default TaskScheduler) is close enough.
You can verify that by looking at the source for YieldAwaiter and see that it uses ThreadPool.QueueUserWorkItem/ThreadPool.UnsafeQueueUserWorkItem when TaskScheduler.Current is the default one (i.e. thread pool) and Task.Factory.StartNew when it isn't.
You can however create your own awaitable (as I did) that mimics YieldAwaitable but disregards the SynchronizationContext:
async Task Run(int input)
{
await new NoContextYieldAwaitable();
// executed on a ThreadPool thread
}
public struct NoContextYieldAwaitable
{
public NoContextYieldAwaiter GetAwaiter() { return new NoContextYieldAwaiter(); }
public struct NoContextYieldAwaiter : INotifyCompletion
{
public bool IsCompleted { get { return false; } }
public void OnCompleted(Action continuation)
{
var scheduler = TaskScheduler.Current;
if (scheduler == TaskScheduler.Default)
{
ThreadPool.QueueUserWorkItem(RunAction, continuation);
}
else
{
Task.Factory.StartNew(continuation, CancellationToken.None, TaskCreationOptions.PreferFairness, scheduler);
}
}
public void GetResult() { }
private static void RunAction(object state) { ((Action)state)(); }
}
}
Note: I don't recommend actually using NoContextYieldAwaitable, it's just an answer to your question. You should be using Task.Run (or Task.Factory.StartNew with a specific TaskScheduler)
I noticed you edited your question after you accepted the existing answer, so perhaps you're interested in more rants on the subject. Here you go :)
It's recommended that one use ConfigureAwait(false) whenever when you
can, especially in libraries because it can help avoid deadlocks and
improve performance.
It's recommended so, only if you're absolutely sure that any API you're calling in your implementation (including Framework APIs) doesn't depend on any properties of synchronization context. That's especially important for a library code, and even more so if the library is suitable for both client-side and server-side use. E.g, CurrentCulture is a common overlook: it would never be an issue for a desktop app, but it well may be for an ASP.NET app.
Back to your code:
private async Task<TState> NextChunk(...)
{
await Task.Yield(); // ** causes deadlock
var nextState = await enumerable.GetMore(...);
// ...
return nextState;
}
Most likely, the deadlock is caused by the client of your library, because they use Task.Result (or Task.Wait, Task.WaitAll, Task.IAsyncResult.AsyncWaitHandle etc, let them search) somewhere in the outer frame of the call chain. Albeit Task.Yield() is redundant here, this is not your problem in the first place, but rather theirs: they shouldn't be blocking on the asynchronous APIs and should be using "Async All the Way", as also explained in the Stephen Cleary's article you linked.
Removing Task.Yield() may or may not solve this problem, because enumerable.GetMore() can also use some await SomeApiAsync() without ConfigureAwait(false), thus posting the continuation back to the caller's synchronization context. Moreover, "SomeApiAsync" can happen to be a well established Framework API which is still vulnerable to a deadlock, like SendMailAsync, we'll get back to it later.
Overall, you should only be using Task.Yield() if for some reason you want to return to the caller immediately ("yield" the execution control back to the caller), and then continue asynchronously, at the mercy of the SynchronizationContext installed on the calling thread (or ThreadPool, if SynchronizationContext.Current == null). The continuation well may be executed on the same thread upon the next iteration of the app's core message loop. Some more details can be found here:
Task.Yield - real usages?
So, the right thing would be to avoid blocking code all the way. However, say, you still want to make your code deadlock-proof, you don't care about synchronization context and you're sure the same is true about any system or 3rd party API you use in your implementation.
Then, instead of reinventing ThreadPoolEx.SwitchTo (which was removed for a good reason), you could just use Task.Run, as suggested in the comments:
private Task<TState> NextChunk(...)
{
// jump to a pool thread without SC to avoid deadlocks
return Task.Run(async() =>
{
var nextState = await enumerable.GetMore(...);
// ...
return nextState;
});
}
IMO, this is still a hack, with the same net effect, although a much more readable one than using a variation of ThreadPoolEx.SwitchTo(). Same as SwitchTo, it still has an associated cost: a redundant thread switch which may hurt ASP.NET performance.
There is another (IMO better) hack, which I proposed here to address the deadlock with aforementioned SendMailAsync. It doesn't incur an extra thread switch:
private Task<TState> NextChunk(...)
{
return TaskExt.WithNoContext(async() =>
{
var nextState = await enumerable.GetMore(...);
// ...
return nextState;
});
}
public static class TaskExt
{
public static Task<TResult> WithNoContext<TResult>(Func<Task<TResult>> func)
{
Task<TResult> task;
var sc = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(null);
task = func(); // do not await here
}
finally
{
SynchronizationContext.SetSynchronizationContext(sc);
}
return task;
}
}
This hack works in the way it temporarily removes the synchronization context for the synchronous scope of the original NextChunk method, so it won't be captured for the 1st await continuation inside the async lambda, effectively solving the deadlock problem.
Stephen has provided a slightly different implementation while answering the same question. His IgnoreSynchronizationContext restores the original synchronization context on whatever happens to be the continuation's thread after await (which could be a completely different, random pool thread). I'd rather not restore it after await at all, as long as I don't care about it.
Inasmuch as the useful and legit API you're looking for is missing, I filed this request proposing its addition to .NET.
I also added it to vs-threading so that the next release of the Microsoft.VisualStudio.Threading NuGet package will include this API. Note that this library is not VS-specific, so you can use it in your app.
I need to write some asynchronous code that essentially attempts to repeatedly talk to and initialise a database. Quite often the first attempt will fail hence the requirement for it to retry.
In days of old I would have used a pattern similar to:
void WaitForItToWork()
{
bool succeeded = false;
while (!succeeded)
{
// do work
succeeded = outcome; // if it worked, mark as succeeded, else retry
Threading.Thread.Sleep(1000); // arbitrary sleep
}
}
I realise a lot of changes have been made recently to .NET with regards to async patterns so my question really is this the best method to use or is it worth while exploring the async stuff and if so how do I implement this pattern in async?
Update
Just to clarify, I want to spawn this work asynchronously so that the method which spawns it does not have to wait for it to finish as it will be spawned in the constructor of a service so the constructor must return instantly.
You could refactor that fragment like this:
async Task<bool> WaitForItToWork()
{
bool succeeded = false;
while (!succeeded)
{
// do work
succeeded = outcome; // if it worked, make as succeeded, else retry
await Task.Delay(1000); // arbitrary delay
}
return succeeded;
}
Apparently, the only benefit it would give you is more efficient use of thread pool, because it doesn't always take a whole thread to make the delay happen.
Depending on how you obtain outcome, there may be much more efficient ways to get this job done using async/await. Often you may have something like GetOutcomeAsync() which would make a web service, database or socket call asynchronously in a natural way, so you'd just do var outcome = await GetOutcomeAsync().
It's important to take into account that WaitForItToWork will be split into parts by compiler and the part from await line will be continued asynchronously. Here's perhaps the best explanation on how it's done internally. The thing is, usually at some point of your code you'd need to synchronize on the result of the async task. E.g.:
private void Form1_Load(object sender, EventArgs e)
{
Task<bool> task = WaitForItToWork();
task.ContinueWith(_ => {
MessageBox.Show("WaitForItToWork done:" + task.Result.toString()); // true or false
}, TaskScheduler.FromCurrentSynchronizationContext());
}
You could have simply done this:
private async void Form1_Load(object sender, EventArgs e)
{
bool result = await WaitForItToWork();
MessageBox.Show("WaitForItToWork done:" + result.toString()); // true or false
}
That would however make Form1_Load an async method too.
[UPDATE]
Below is my attempt to to illustrate what async/await actually does in this case. I created two versions of the same logic, WaitForItToWorkAsync (using async/await) and WaitForItToWorkAsyncTap (using TAP pattern without async/await). The frist version is quite trivial, unlike the second one. Thus, while async/await is largely the compiler's syntactic sugar, it makes asynchronous code much easier to write and understand.
// fake outcome() method for testing
bool outcome() { return new Random().Next(0, 99) > 50; }
// with async/await
async Task<bool> WaitForItToWorkAsync()
{
var succeeded = false;
while (!succeeded)
{
succeeded = outcome(); // if it worked, make as succeeded, else retry
await Task.Delay(1000);
}
return succeeded;
}
// without async/await
Task<bool> WaitForItToWorkAsyncTap()
{
var context = TaskScheduler.FromCurrentSynchronizationContext();
var tcs = new TaskCompletionSource<bool>();
var succeeded = false;
Action closure = null;
closure = delegate
{
succeeded = outcome(); // if it worked, make as succeeded, else retry
Task.Delay(1000).ContinueWith(delegate
{
if (succeeded)
tcs.SetResult(succeeded);
else
closure();
}, context);
};
// start the task logic synchronously
// it could end synchronously too! (e.g, if we used 'Task.Delay(0)')
closure();
return tcs.Task;
}
// start both tasks and handle the completion of each asynchronously
private void StartWaitForItToWork()
{
WaitForItToWorkAsync().ContinueWith((t) =>
{
MessageBox.Show("WaitForItToWorkAsync complete: " + t.Result.ToString());
}, TaskScheduler.FromCurrentSynchronizationContext());
WaitForItToWorkAsyncTap().ContinueWith((t) =>
{
MessageBox.Show("WaitForItToWorkAsyncTap complete: " + t.Result.ToString());
}, TaskScheduler.FromCurrentSynchronizationContext());
}
// await for each tasks (StartWaitForItToWorkAsync itself is async)
private async Task StartWaitForItToWorkAsync()
{
bool result = await WaitForItToWorkAsync();
MessageBox.Show("WaitForItToWorkAsync complete: " + result.ToString());
result = await WaitForItToWorkAsyncTap();
MessageBox.Show("WaitForItToWorkAsyncTap complete: " + result.ToString());
}
A few words on threading. There is no additional threads explicitly created here. Internally, Task.Delay() implementation may use pool threads (I suspect they use Timer Queues), but in this particular example (a WinForms app), the continuation after await will happen on the same UI thread. In other execution environments (e.g. a console app), it might continue on a different thread. IMO, this article by Stephen Cleary is a must-read to understand async/await threading concepts.
If the task is asynchronous you can try with:
async Task WaitForItToWork()
{
await Task.Run(() =>
{
bool succeeded = false;
while (!succeeded)
{
// do work
succeeded = outcome; // if it worked, make as succeeded, else retry
System.Threading.Thread.Sleep(1000); // arbitrary sleep
}
});
}
See http://msdn.microsoft.com/en-us/library/hh195051.aspx.
Just provide another solution
public static void WaitForCondition(Func<bool> predict)
{
Task.Delay(TimeSpan.FromMilliseconds(1000)).ContinueWith(_ =>
{
var result = predict();
// the condition result is false, and we need to wait again.
if (result == false)
{
WaitForCondition(predict);
}
});
}
You don't really need WaitItForWork method, just await for a database initialization task:
async Task Run()
{
await InitializeDatabase();
// Do what you need after database is initialized
}
async Task InitializeDatabase()
{
// Perform database initialization here
}
If you have multiple pieces of code that call to WaitForItToWork then you need to wrap database initialization into a Task and await it in all workers, for example:
readonly Task _initializeDatabaseTask = InitializeDatabase();
async Task Worker1()
{
await _initializeDatabaseTask;
// Do what you need after database is initialized
}
async Task Worker2()
{
await _initializeDatabaseTask;
// Do what you need after database is initialized
}
static async Task InitializeDatabase()
{
// Initialize your database here
}