I'm having a bad time with this. I'm trying to make a async method that returns the contents of a local file as string. This is my approach:
private static async Task<string> ReadContentsAsString(string fileName)
{
var uri = new Uri(string.Format(#"ms-appx:///{0}", fileName));
var file = await StorageFile.GetFileFromApplicationUriAsync(uri).AsTask().ConfigureAwait(false);
var stream = await file.OpenStreamForReadAsync().ConfigureAwait(false);
using (var streamReader = new StreamReader(stream))
{
return await streamReader.ReadToEndAsync();
}
}
Unfortunately, after the execution reaches the end of my method, the application waits forever. It hangs completely. It's being called at the very beginning, when the splash screen still shows (Windows Phone 8.1)
What do I miss?
I suspect that further up your call stack, your code has a call to Task.Wait or Task<T>.Result. This can cause a deadlock that I describe on my blog.
In summary, what happens is that when await is used on a task, by default it will capture the current "context" and use that context to resume the async method. In this case, the context is the UI context, which is associated with the single UI thread. If code further up the call stack is calling Wait or Result, then it's blocking the UI thread, which prevents the async method from finishing.
Your method is working as it should. I suspect that you are encountering this issue while debugging.
I also have noticed (sometimes) such a behaviour when debugging asyc method (here is a link to the question) - the program never returns from the method and just hangs - I don't know the exact reason of this. To test it just try to run your method like this - for example upon button click:
private async void firstBtn_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Before method");
string readValue = await ReadContentsAsString("TextFile1.txt");
Debug.WriteLine(string.Format("Read value: {0}", readValue));
}
As I've tested on device - it should work, but if I set a breakpoint inside your method - it will hang.
Related
I'm calling a 3rd party library from my C# code, and have found that ctx.CreateSiteAsync(communicationSiteInfo).Wait(); works well, while await ctx.CreateSiteAsync(communicationSiteInfo); causes the application to crash. As .Wait() to the best of my knowledge causes the thread to block, I'm interested inn getting the await approach to work.
Here an extract from my code to put the above calls in context:
public async Task createSite(string base_url, SiteConfig siteConfig) {
using(var ctx = new OfficeDevPnP.Core.AuthenticationManager().GetAppOnlyAuthenticatedContext(base_url, this.applicationId, this.applicationSecret)) {
ctx.Load(ctx.Web, p => p.Title);
ctx.ExecuteQuery();
CommunicationSiteCollectionCreationInformation communicationSiteInfo = new CommunicationSiteCollectionCreationInformation {
Title = siteConfig.title,
Url = siteConfig.url,
SiteDesign = siteConfig.siteDesign,
Description = siteConfig.description,
Owner = siteConfig.ownerEmailAddress
};
try {
// This works: ctx.CreateSiteAsync(communicationSiteInfo).Wait();
await ctx.CreateSiteAsync(communicationSiteInfo);
} catch....
If I'm not mistaking, the function I'm calling it this one: ClientContextExtensions.cs.
I'm pretty new to C#, so perhaps the reason for the application crashing is obvious, but I can't see why the await wouldn't work, as the function I'm calling has async Task in it's definition.
EDIT: The weird thing regarding the exception is that the application simply crashes, and the catch clause is never reached. I don't know, but maybe this has something to do with threading or context or something in that the exception thrown in the async function call are not returned to the current thread. The application crashes on the await ctx.CreateSiteAsync(communicationSiteInfo); call.
EDIT 2: It looks as though I can simplify the issue at hand, but using this as an example instead:
public async Task StartMessageQueuePollAsync()
{
while (true)
{
await Task.Delay(1000).ConfigureAwait(false);
}
This causes the code to crash on await Task.Delay(1000).ConfigureAwait(false);. If is instead use Task.Delay(1000).Wait(), the code works as expected.
I see your answer, but I don't think that's the root cause. It's perfectly fine to use static async Task Main(), as long as your project is using C# 7.0 or higher (when that was introduced). If changing that (and making everything else synchronous, as you'd have to after removing async) made the symptom go away, then that means that somewhere along your call stack, you were missing an await.
For example, this works just fine:
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
Console.WriteLine("Hello.");
await Pause();
Console.WriteLine("All done");
}
public static async Task Pause() {
await Task.Delay(1000);
Console.WriteLine("Done pausing");
}
}
But if you remove the await in Main, then the application would end before "Done pausing" is printed. This is because async methods run synchronously at first, but return at the first await that acts on an incomplete Task. (Pause() returns a Task when it hits await Task.Delay(1000) - before the waiting is completed)
So if you don't await an async method, then your code will just move on to the next line before the work is done. Sometimes you actually want this, but often not.
Since it otherwise runs synchronously, replacing the await with .Wait() would halt the thread and the method would not return, making it suddenly "work".
In your code, that means that either you weren't awaiting createSite() or weren't awaiting whatever called the method that called createSite(), etc.
Microsoft has a series of very well-written articles about asynchronous articles that are worth reading. Start here: Asynchronous programming with async and await
Thanks for the comments on my initial post. I got it working now, and believe it's because of I defined the Main method to be async, like this:
static async Task Main().
First, sorry for yet another "why my async action hangs" question but I believe this question is different enough.
Surveying dozens of similar questions, the problem of async action deadlock is either in locking yourself out (.Result), using limited resources or using library components incorrectly (web requests seems popular). In the following example, I cannot find any from above:
private async Task ExecuteAsync(Task<int> task)
{
// entering on current thread, that is the main UI thread
await task // execute "task" asynchronnously (on a different thread)
.ConfigureAwait(false); // when done, no need to return to main thread
MessageBox.Show("success"); // succes indicator
}
public MainWindow() //wpf window ctor
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var task = new Task<int>(() => 42); // make an Action wrapping sychronnous method
// fire and forget, never caring for .Result, disard even the task
var _ = ExecuteAsync(task).ConfigureAwait(false);
}
I have commented the sample with my best try on exaplaining how things (should) work, but something in my explanation must be wrong. Even though MainWindow ctor does not deadlock, the Action () => 42 is never executed and "success" message is not shown. After some debugging I managed to fix the sample (using Task.FromResult), but I am still not sure what is wrong with it as it is now and even more importantly why.
What is the error in my reasoning and why was the action never executed/finished?
You did not start the task! You only declared it. Simply awaiting it does not "fire" it.
private async Task ExecuteAsync(Task<int> task)
{
// at first do start the task
task.Start();
await task.ConfigureAwait(false);
MessageBox.Show("success");
}
Note that ConfigureAwait(false) does not guarantee that execution will be continued on a different thread. It only says that you don't need it to be resumed on the original thread. And resuming UI work (like MessageBox.Show()) on a non-UI thread is not recommended.
As NineBerry pointed out, if you want to wrap a synchronous method and let it run on a different thread, you should use Task.Run():
var task = Task.Run(() => YourSynchronousCall());
I had a situation recently where I had an ASP.NET WebAPI controller that needed to perform two web requests to another REST service inside its action method. I had written my code to have functionality separated cleanly into separate methods, which looked a little like this example:
public class FooController : ApiController
{
public IHttpActionResult Post(string value)
{
var results = PerformWebRequests();
// Do something else here...
}
private IEnumerable<string> PerformWebRequests()
{
var result1 = PerformWebRequest("service1/api/foo");
var result = PerformWebRequest("service2/api/foo");
return new string[] { result1, result2 };
}
private string PerformWebRequest(string api)
{
using (HttpClient client = new HttpClient())
{
// Call other web API and return value here...
}
}
}
Because I was using HttpClient all web requests had to be async. I've never used async/await before so I started naively adding in the keywords. First I added the async keyword to the PerformWebRequest(string api) method but then the caller complained that the PerformWebRequests() method has to be async too in order to use await. So I made that async but now the caller of that method must be async too, and so on.
What I want to know is how far down the rabbit hole must everything be marked async to just work? Surely there would come a point where something has to run synchronously, in which case how is that handled safely? I've already read that calling Task.Result is a bad idea because it could cause deadlocks.
What I want to know is how far down the rabbit hole must everything be
marked async to just work? Surely there would come a point where
something has to run synchronously
No, there shouldn't be a point where anything runs synchronously, and that is what async is all about. The phrase "async all the way" actually means all the way up the call stack.
When you process a message asynchronously, you're letting your message loop process requests while your truly asynchronous method runs, because when you go deep down the rabit hole, There is no Thread.
For example, when you have an async button click event handler:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await DoWorkAsync();
// Do more stuff here
}
private Task DoWorkAsync()
{
return Task.Delay(2000); // Fake work.
}
When the button is clicked, runs synchronously until hitting the first await. Once hit, the method will yield control back to the caller, which means the button event handler will free the UI thread, which will free the message loop to process more requests in the meanwhile.
The same goes for your use of HttpClient. For example, when you have:
public async Task<IHttpActionResult> Post(string value)
{
var results = await PerformWebRequests();
// Do something else here...
}
private async Task<IEnumerable<string>> PerformWebRequests()
{
var result1 = await PerformWebRequestAsync("service1/api/foo");
var result = await PerformWebRequestAsync("service2/api/foo");
return new string[] { result1, result2 };
}
private async string PerformWebRequestAsync(string api)
{
using (HttpClient client = new HttpClient())
{
await client.GetAsync(api);
}
// More work..
}
See how the async keyword went up all the way to the main method processing the POST request. That way, while the async http request is handled by the network device driver, your thread returns to the ASP.NET ThreadPool and is free to process more requests in the meanwhile.
A Console Application is a special case, since when the Main method terminates, unless you spin a new foreground thread, the app will terminate. There, you have to make sure that if the only call is an async call, you'll have to explicitly use Task.Wait or Task.Result. But in that case the default SynchronizationContext is the ThreadPoolSynchronizationContext, where there isn't a chance to cause a deadlock.
To conclude, async methods shouldn't be processed synchronously at the top of the stack, unless there is an exotic use case (such as a Console App), they should flow asynchronously all the way allowing the thread to be freed when possible.
You need to "async all the way up" to the very top of the call stack, where you reach a message loop that can process all of the asynchronous requests.
I have a multi-tier .Net 4.5 application calling a method using C#'s new async and await keywords that just hangs and I can't see why.
At the bottom I have an async method that extents our database utility OurDBConn (basically a wrapper for the underlying DBConnection and DBCommand objects):
public static async Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
T result = await Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
return result;
}
Then I have a mid level async method that calls this to get some slow running totals:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var result = await this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
return result;
}
Finally I have a UI method (an MVC action) that runs synchronously:
Task<ResultClass> asyncTask = midLevelClass.GetTotalAsync(...);
// do other stuff that takes a few seconds
ResultClass slowTotal = asyncTask.Result;
The problem is that it hangs on that last line forever. It does the same thing if I call asyncTask.Wait(). If I run the slow SQL method directly it takes about 4 seconds.
The behaviour I'm expecting is that when it gets to asyncTask.Result, if it's not finished it should wait until it is, and once it is it should return the result.
If I step through with a debugger the SQL statement completes and the lambda function finishes, but the return result; line of GetTotalAsync is never reached.
Any idea what I'm doing wrong?
Any suggestions to where I need to investigate in order to fix this?
Could this be a deadlock somewhere, and if so is there any direct way to find it?
Yep, that's a deadlock all right. And a common mistake with the TPL, so don't feel bad.
When you write await foo, the runtime, by default, schedules the continuation of the function on the same SynchronizationContext that the method started on. In English, let's say you called your ExecuteAsync from the UI thread. Your query runs on the threadpool thread (because you called Task.Run), but you then await the result. This means that the runtime will schedule your "return result;" line to run back on the UI thread, rather than scheduling it back to the threadpool.
So how does this deadlock? Imagine you just have this code:
var task = dataSource.ExecuteAsync(_ => 42);
var result = task.Result;
So the first line kicks off the asynchronous work. The second line then blocks the UI thread. So when the runtime wants to run the "return result" line back on the UI thread, it can't do that until the Result completes. But of course, the Result can't be given until the return happens. Deadlock.
This illustrates a key rule of using the TPL: when you use .Result on a UI thread (or some other fancy sync context), you must be careful to ensure that nothing that Task is dependent upon is scheduled to the UI thread. Or else evilness happens.
So what do you do? Option #1 is use await everywhere, but as you said that's already not an option. Second option which is available for you is to simply stop using await. You can rewrite your two functions to:
public static Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
return Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
}
public static Task<ResultClass> GetTotalAsync( ... )
{
return this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
}
What's the difference? There's now no awaiting anywhere, so nothing being implicitly scheduled to the UI thread. For simple methods like these that have a single return, there's no point in doing an "var result = await...; return result" pattern; just remove the async modifier and pass the task object around directly. It's less overhead, if nothing else.
Option #3 is to specify that you don't want your awaits to schedule back to the UI thread, but just schedule to the thread pool. You do this with the ConfigureAwait method, like so:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var resultTask = this.DBConnection.ExecuteAsync<ResultClass>(
ds => return ds.Execute("select slow running data into result");
return await resultTask.ConfigureAwait(false);
}
Awaiting a task normally would schedule to the UI thread if you're on it; awaiting the result of ContinueAwait will ignore whatever context you are on, and always schedule to the threadpool. The downside of this is you have to sprinkle this everywhere in all functions your .Result depends on, because any missed .ConfigureAwait might be the cause of another deadlock.
This is the classic mixed-async deadlock scenario, as I describe on my blog. Jason described it well: by default, a "context" is saved at every await and used to continue the async method. This "context" is the current SynchronizationContext unless it it null, in which case it is the current TaskScheduler. When the async method attempts to continue, it first re-enters the captured "context" (in this case, an ASP.NET SynchronizationContext). The ASP.NET SynchronizationContext only permits one thread in the context at a time, and there is already a thread in the context - the thread blocked on Task.Result.
There are two guidelines that will avoid this deadlock:
Use async all the way down. You mention that you "can't" do this, but I'm not sure why not. ASP.NET MVC on .NET 4.5 can certainly support async actions, and it's not a difficult change to make.
Use ConfigureAwait(continueOnCapturedContext: false) as much as possible. This overrides the default behavior of resuming on the captured context.
I was in the same deadlock situation but in my case calling an async method from a sync method, what works for me was:
private static SiteMetadataCacheItem GetCachedItem()
{
TenantService TS = new TenantService(); // my service datacontext
var CachedItem = Task.Run(async ()=>
await TS.GetTenantDataAsync(TenantIdValue)
).Result; // dont deadlock anymore
}
is this a good approach, any idea?
Just to add to the accepted answer (not enough rep to comment), I had this issue arise when blocking using task.Result, event though every await below it had ConfigureAwait(false), as in this example:
public Foo GetFooSynchronous()
{
var foo = new Foo();
foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET
return foo;
}
private async Task<string> GetInfoAsync()
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
The issue actually lay with the external library code. The async library method tried to continue in the calling sync context, no matter how I configured the await, leading to deadlock.
Thus, the answer was to roll my own version of the external library code ExternalLibraryStringAsync, so that it would have the desired continuation properties.
wrong answer for historical purposes
After much pain and anguish, I found the solution buried in this blog post (Ctrl-f for 'deadlock'). It revolves around using task.ContinueWith, instead of the bare task.Result.
Previously deadlocking example:
public Foo GetFooSynchronous()
{
var foo = new Foo();
foo.Info = GetInfoAsync.Result; // often deadlocks in ASP.NET
return foo;
}
private async Task<string> GetInfoAsync()
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
Avoid the deadlock like this:
public Foo GetFooSynchronous
{
var foo = new Foo();
GetInfoAsync() // ContinueWith doesn't run until the task is complete
.ContinueWith(task => foo.Info = task.Result);
return foo;
}
private async Task<string> GetInfoAsync
{
return await ExternalLibraryStringAsync().ConfigureAwait(false);
}
quick answer :
change this line
ResultClass slowTotal = asyncTask.Result;
to
ResultClass slowTotal = await asyncTask;
why? you should not use .result to get the result of tasks inside most applications except console applications if you do so your program will hang when it gets there
you can also try the below code if you want to use .Result
ResultClass slowTotal = Task.Run(async ()=>await asyncTask).Result;
I am writing an app for windows 8.1 tablet and I am trying to read data from a text file I have saved (this text file is just over 1kb). The below code I have works on some occasions but mainly fails(debugging/stepping over the code will often see it succeed).
StorageFolder folder = ApplicationData.Current.LocalFolder;
string fileName = "collections.json";
public Dictionary<string, string> masterDataObject;
private async void CallLoad()
{
await this.Load();
}
public async Task<Dictionary<string, string>> Load()
{
//create a file
var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
string fileContents = string.Empty;
if (file != null)
{
//returns a JSON string
fileContents = await FileIO.ReadTextAsync(file);//WHY DOES IT JUMP AT THIS LINE?????
}
Dictionary<string, string> customerFromJSON = JsonCrt.DeserializeObject<Dictionary<string, string>>(fileContents) ?? new Dictiy<string, string>();
masterDataObject = customerFromJSON;
return masterDataObject;
}
After stepping through the code several times I can see at the line
fileContents = await.....
it drops out of the method and continues with the rest of the code that is not in my Load() method.
I have reviewed async and await and have really tried to understand it, but my understanding leaves me confused as to why this is happening.
I was under the belief that await meant that execution would stop until you get a response from the code you are calling (obviously not).
So how should I be using async to make it work properly, or is there a better alternative than this code?
I have looked and tried many options but so had no success, any advice would be gratefully received.
it drops out of the method and continues with the rest of the code that is not in my Load() method
That's exactly what it's ment to do, yield control to the calling site until the asynchronous operation completes.
I'm assuming your problem lays with the fact your CallLoad method is async void instead of async Task, thus cannot be awaited, and that's why you're seeing it continue without waiting for the internal async IO to complete.
I was under the belief that await meant that execution would stop until you get a response from the code you are calling
That is still entirely true, if you await the async operation all the way
So how should I be using async to make it work properly?
async void is ment only for top level event handlers. If CallLoad isn't used as one, it should be async Task and awaited: await CallLoad();
What await does behind the scenes:
it creates a callback which contains the code after await
it calls into the xyzAsync() function, registering the callback.
if the asynchronous operation finishes, the callback is called.
So if you step through the code with a debugger, it will execute some other code if it hits await returning to the code after the await as soon as the asynchronous operation has finished.