async library calls relying on each other and how to handle? - c#

this is a follow on from a previous question I posted Calling an async method using a Task.Run seems wrong?
I thought the code written by the contractor was wrong but following on from the answers provided I'm now wondering if it's the libraries fault. This library exposes two methods that I need to use. One returns a "template" and one consumes part of this template (it does in my implementation anyway). But both are async methods returning Tasks.
To explain my library has methods:
public Task<TemplateInfo> TemplateInfo(TemplateInfoRequest request);
public Task<List<EmailResult>> SendMessageTemplate(SendMessageTemplateRequest request);
I need to call these thus:
public bool SendMessage()
{
var template = TemplateInfo(...);
var message = //use template to create message
var sendResponse = SendMessageTemplate(message);
return sendResponse.Count > 0;
}
So the second call relies on the first. This is where the async doesn't make sense to me. I can't and don't want to run these in parallel. I want to run them in sequence. I want my method to by synchonous.
An answer in my previous question also states:
Since you're blocking on an async method (which you shouldn't do)
there is a chance you'll deadlock.
So how do I access these async methods in such a way that they are processed in turn and return a synconhonous result but do not cause deadlocks?

Async doesn't (necessarily) means parallel.
You can call both async method sequentially without them running in parallel. Simply call the first and await the returned task and then do the same with the second.
var template = await TemplateInfo(...);
var message = //use template to create message
var sendResponse = await SendMessageTemplate(message);
This is still useful compared to synchronous code because while the asynchronous operation is "running" there's no thread needed and so your threads can go work on other parts of your application.
If you would call both and only then await the returned tasks you will (maybe) run in parallel:
var templateTask = TemplateInfo(...);
var sendResponseTask = SendMessageTemplate(message);
await templateTask;
await sendResponseTask;

Related

Method returning task behaving synchronously in C# console app

In a C# console app, I have a repo class with a couple of async methods:
public class SomeRepo
{
internal Task<IList<Foo>> GetAllFooAsync()
{
// this is actually fake-async due to legacy code.
var result = SomeSyncMethod();
return Task.FromResult(result);
}
public Task<IList<Foo>> GetFilteredFooAsync()
{
var allFoos = await GetAllFooAsync().ConfigureAwait(false);
return allFoos.Where(x => x.IsFiltered);
}
}
In Program.cs:
var someRepo = new SomeRepo();
var filteredFoos = someRepo.GetFilteredFooAsync(); // no await
// a couple of additional async calls (to other classes) without await..
// .. followed by:
await Task.WhenAll(filteredFoos, otherTask, anotherTask).ConfigureAwait(false);
What is baffling me is that if I place a break point on the 2nd line in Program.cs, the call to someRepo.GetFilteredFooAsync() does not proceed to the next line, but instead is stuck until the operation is complete (as though it was synchronous). Whereas if I change the call to GetAllFooAsync (in GetFilteredFooAsync) to be wrapped within a Task.Run:
public class SomeRepo
{
internal Task<IList<Foo>> GetAllFooAsync() { // ... }
public Task<IList<Foo>> GetFilteredFooAsync()
{
var allFoos = await Task.Run(() => GetAllFooAsync).ConfigureAwait(false);
return allFoos.Where(x => x.IsFiltered);
}
}
..the operation works as expected this way. Is it because GetAllFooAsync is actually synchronous, but imitating an asynchronous workflow?
EDIT: Reworded the title and added the internals of GetAllFooAsync as I've realized they could be the culprit of the issue.
You've already got some good answers that describe how async doesn't make things asynchronous, how async methods begin executing synchronously, and how await can act synchronously if its task is already completed.
So, let's talk about the design.
internal Task<IList<Foo>> GetAllFooAsync()
{
// this is actually fake-async due to legacy code.
var result = SomeSyncMethod();
return Task.FromResult(result);
}
As noted, this is a synchronous method, but it has an asynchronous signature. This is confusing; if the method is not asynchronous, it would be better with a synchronous API:
internal IList<Foo> GetAllFoo()
{
// this is actually fake-async due to legacy code.
var result = SomeSyncMethod();
return result;
}
and similar for the method that calls it:
public IList<Foo> GetFilteredFoo()
{
var allFoos = GetAllFoo();
return allFoos.Where(x => x.IsFiltered);
}
So now we have synchronous implementations with synchronous APIs. The question now is about consumption. If you are consuming this from ASP.NET, I recommend consuming them synchronously. However, if you are consuming them from a GUI application, then you can use Task.Run to offload the synchronous work to a thread pool thread, and then treat it as though it were asynchronous:
var someRepo = new SomeRepo();
var filteredFoos = Task.Run(() => someRepo.GetFilteredFoo()); // no await
// a couple of additional async calls (to other classes) without await..
// .. followed by:
await Task.WhenAll(filteredFoos, otherTask, anotherTask).ConfigureAwait(false);
Specifically, I do not recommend using Task.Run to implement, e.g., GetAllFooAsync. You should use Task.Run to call methods, not to implement them, and Task.Run should mostly be used to call synchronous code from a GUI thread (i.e., not on ASP.NET).
Presence of asynckeyword doesn't make a method asynchronous it just signals compiler to make conversion the code of the method into state machine class which is ready to be used with asynchronous flows. Effectively a method becomes asynchronous when it does an asynchronous operation such as I/O, offloading work to another thread, etc., and in that case it consists of 3 parts: the synchronous part which precedes an asynchronous operation, call of asynchronous operation which initiates the operation and returns control to calling thread, and a continuation. In your case the last two parts are absent so your call is synchronous.
Is it because GetAllFooAsync is actually synchronous, but imitating an asynchronous workflow?
Yes, Task.FromResult returns a task that is immediately RanToCompletion so it is synchronous. People often forget that Tasks may in some cases already be complete when they are returned and therefore do not run asynchronously.
This method creates a Task object whose Task.Result property is result and whose Status property is RanToCompletion. The method is commonly used when the return value of a task is immediately known without executing a longer code path. The example provides an illustration.

Calling async methods from non-async code

I'm in the process of updating a library that has an API surface that was built in .NET 3.5. As a result, all methods are synchronous. I can't change the API (i.e., convert return values to Task) because that would require that all callers change. So I'm left with how to best call async methods in a synchronous way. This is in the context of ASP.NET 4, ASP.NET Core, and .NET/.NET Core console applications.
I may not have been clear enough - the situation is that I have existing code that is not async aware, and I want to use new libraries such as System.Net.Http and the AWS SDK that support only async methods. So I need to bridge the gap, and be able to have code that can be called synchronously but then can call async methods elsewhere.
I've done a lot of reading, and there are a number of times this has been asked and answered.
Calling async method from non async method
Synchronously waiting for an async operation, and why does Wait() freeze the program here
Calling an async method from a synchronous method
How would I run an async Task<T> method synchronously?
Calling async method synchronously
How to call asynchronous method from synchronous method in C#?
The problem is that most of the answers are different! The most common approach I've seen is use .Result, but this can deadlock. I've tried all the following, and they work, but I'm not sure which is the best approach to avoid deadlocks, have good performance, and plays nicely with the runtime (in terms of honoring task schedulers, task creation options, etc). Is there a definitive answer? What is the best approach?
private static T taskSyncRunner<T>(Func<Task<T>> task)
{
T result;
// approach 1
result = Task.Run(async () => await task()).ConfigureAwait(false).GetAwaiter().GetResult();
// approach 2
result = Task.Run(task).ConfigureAwait(false).GetAwaiter().GetResult();
// approach 3
result = task().ConfigureAwait(false).GetAwaiter().GetResult();
// approach 4
result = Task.Run(task).Result;
// approach 5
result = Task.Run(task).GetAwaiter().GetResult();
// approach 6
var t = task();
t.RunSynchronously();
result = t.Result;
// approach 7
var t1 = task();
Task.WaitAll(t1);
result = t1.Result;
// approach 8?
return result;
}
So I'm left with how to best call async methods in a synchronous way.
First, this is an OK thing to do. I'm stating this because it is common on Stack Overflow to point this out as a deed of the devil as a blanket statement without regard for the concrete case.
It is not required to be async all the way for correctness. Blocking on something async to make it sync has a performance cost that might matter or might be totally irrelevant. It depends on the concrete case.
Deadlocks come from two threads trying to enter the same single-threaded synchronization context at the same time. Any technique that avoids this reliably avoids deadlocks caused by blocking.
In your code snippet, all calls to .ConfigureAwait(false) are pointless because the return value is not awaited. ConfigureAwait returns a struct that, when awaited, exhibits the behavior that you requested. If that struct is simply dropped, it does nothing.
RunSynchronously is invalid to use because not all tasks can be processed that way. This method is meant for CPU-based tasks, and it can fail to work under certain circumstances.
.GetAwaiter().GetResult() is different from Result/Wait() in that it mimics the await exception propagation behavior. You need to decide if you want that or not. (So research what that behavior is; no need to repeat it here.) If your task contains a single exception then the await error behavior is usually convenient and has little downside. If there are multiple exceptions, for example from a failed Parallel loop where multiple tasks failed, then await will drop all exceptions but the first one. That makes debugging harder.
All these approaches have similar performance. They will allocate an OS event one way or another and block on it. That's the expensive part. The other machinery is rather cheap compared to that. I don't know which approach is absolutely cheapest.
In case an exception is being thrown, that is going to be the most expensive part. On .NET 5, exceptions are processed at a rate of at most 200,000 per second on a fast CPU. Deep stacks are slower, and the task machinery tends to rethrow exceptions multiplying their cost. There are ways of blocking on a task without the exception being rethrown, for example task.ContinueWith(_ => { }, TaskContinuationOptions.ExecuteSynchronously).Wait();.
I personally like the Task.Run(() => DoSomethingAsync()).Wait(); pattern because it avoids deadlocks categorically, it is simple and it does not hide some exceptions that GetResult() might hide. But you can use GetResult() as well with this.
I'm in the process of updating a library that has an API surface that was built in .NET 3.5. As a result, all methods are synchronous. I can't change the API (i.e., convert return values to Task) because that would require that all callers change. So I'm left with how to best call async methods in a synchronous way.
There is no universal "best" way to perform the sync-over-async anti-pattern. Only a variety of hacks that each have their own drawbacks.
What I recommend is that you keep the old synchronous APIs and then introduce asynchronous APIs alongside them. You can do this using the "boolean argument hack" as described in my MSDN article on Brownfield Async.
First, a brief explanation of the problems with each approach in your example:
ConfigureAwait only makes sense when there is an await; otherwise, it does nothing.
Result will wrap exceptions in an AggregateException; if you must block, use GetAwaiter().GetResult() instead.
Task.Run will execute its code on a thread pool thread (obviously). This is fine only if the code can run on a thread pool thread.
RunSynchronously is an advanced API used in extremely rare situations when doing dynamic task-based parallelism. You're not in that scenario at all.
Task.WaitAll with a single task is the same as just Wait().
async () => await x is just a less-efficient way of saying () => x.
Blocking on a task started from the current thread can cause deadlocks.
Here's the breakdown:
// Problems (1), (3), (6)
result = Task.Run(async () => await task()).ConfigureAwait(false).GetAwaiter().GetResult();
// Problems (1), (3)
result = Task.Run(task).ConfigureAwait(false).GetAwaiter().GetResult();
// Problems (1), (7)
result = task().ConfigureAwait(false).GetAwaiter().GetResult();
// Problems (2), (3)
result = Task.Run(task).Result;
// Problems (3)
result = Task.Run(task).GetAwaiter().GetResult();
// Problems (2), (4)
var t = task();
t.RunSynchronously();
result = t.Result;
// Problems (2), (5)
var t1 = task();
Task.WaitAll(t1);
result = t1.Result;
Instead of any of these approaches, since you have existing, working synchronous code, you should use it alongside the newer naturally-asynchronous code. For example, if your existing code used WebClient:
public string Get()
{
using (var client = new WebClient())
return client.DownloadString(...);
}
and you want to add an async API, then I would do it like this:
private async Task<string> GetCoreAsync(bool sync)
{
using (var client = new WebClient())
{
return sync ?
client.DownloadString(...) :
await client.DownloadStringTaskAsync(...);
}
}
public string Get() => GetCoreAsync(sync: true).GetAwaiter().GetResult();
public Task<string> GetAsync() => GetCoreAsync(sync: false);
or, if you must use HttpClient for some reason:
private string GetCoreSync()
{
using (var client = new WebClient())
return client.DownloadString(...);
}
private static HttpClient HttpClient { get; } = ...;
private async Task<string> GetCoreAsync(bool sync)
{
return sync ?
GetCoreSync() :
await HttpClient.GetString(...);
}
public string Get() => GetCoreAsync(sync: true).GetAwaiter().GetResult();
public Task<string> GetAsync() => GetCoreAsync(sync: false);
With this approach, your logic would go into the Core methods, which may be run synchronously or asynchronously (as determined by the sync parameter). If sync is true, then the core methods must return an already-completed task. For implemenation, use synchronous APIs to run synchronously, and use asynchronous APIs to run asynchronously.
Eventually, I recommend deprecating the synchronous APIs.
I just went thru this very thing with the AWS S3 SDK. Used to be sync, and I built a bunch of code on that, but now it's async. And that's fine: they changed it, nothing to be gained by moaning about it, move on.So I need to update my app, and my options are to either refactor a large part of my app to be async, or to "hack" the S3 async API to behave like sync.I'll eventually get around to the larger async refactoring - there are many benefits - but for today I have bigger fish to fry so I chose to fake the sync.Original sync code was ListObjectsResponse response = api.ListObjects(request); and a really simple async equivalent that works for me is Task<ListObjectsV2Response> task = api.ListObjectsV2Async(rq2);ListObjectsV2Response rsp2 = task.GetAwaiter().GetResult();
While I get it that purists might pillory me for this, the reality is that this is just one of many pressing issues and I have finite time so I need to make tradeoffs. Perfect? No. Works? Yes.
You Can Call Async Method From non-async method .Check below Code .
public ActionResult Test()
{
TestClass result = Task.Run(async () => await GetNumbers()).GetAwaiter().GetResult();
return PartialView(result);
}
public async Task<TestClass> GetNumbers()
{
TestClass obj = new TestClass();
HttpResponseMessage response = await APICallHelper.GetData(Functions.API_Call_Url.GetCommonNumbers);
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
obj = JsonConvert.DeserializeObject<TestClass>(result);
}
return obj;
}

Method that returns an object be able to await a task

I have a method that returns a DropboxClient and I need to await a method to be able to get an AccessToken required to create this DropboxClient. The snippet of code where I have the problem is:
OAuth2Response authUriComplete =
await Dropbox.Api.DropboxOAuth2Helper.ProcessCodeFlowAsync(token,
options.ClientId, options.ClientSecret);
var dbx = new DropboxClient(authUriComplete.AccessToken);
return dbx;
So I can't figure out how to get this method working, I need to create a method that returns me the DropboxClient, I know that I could return the task and then await it outside the method but that isn't what I need.
Once you start with async/await, you kind of need to follow that up the chain. So your method should probably look like
public async Task<DropboxClient> GetClient()
{
OAuth2Response authUriComplete =
await Dropbox.Api.DropboxOAuth2Helper.ProcessCodeFlowAsync(token, options.ClientId, options.ClientSecret);
return new DropboxClient(authUriComplete.AccessToken);
}
And you would call that as:
var dbx = await GetClient();
If you wanted to not use await there you can also do
var dbx = GetClient().Result;
I need to create a method that returns me the DropboxClient, I know that I could return the task and then await it outside the method but that isn't what I need.
If you are consuming an asynchronous operation, then your consuming method should also be asynchronous. This is the natural, proper way to use async/await. I call this "async all the way" in my article on async best practices.
There are some scenarios where existing code makes this infeasible, or out-of-date third-party or framework code makes this impossible. In this case, you can use one of the hacks described in my article on brownfield async development.
Please note that there is no hack that works in all scenarios! Every hack has some kind of drawback. In the case of the blocking hack, the drawback is a potential deadlock.
The await keyword will suspend execution of the method until it completes. therefore dbx won't be executed until after authUriComplete has its value, and once it does it will return the dropboxclient.
However, depending on the rest of the code, it may continue execution in the caller before this function returns. If that is the issue, you need to organise your code such that whatever you need done after the dropboxclient is returned awaits this happening.
Why do you think you don't need to await the task? You can get the Dropbox client by setting it up using the Task<DropboxClient> rather than just Task.
See Jamiec's answer for detail.

How to call an asynchronous (await) method synchronously?

I'm using the .NET API available from parse.com,
https://parse.com/docs/dotnet_guide#objects-saving
A snippet of my code looks like this;
public async void UploadCurrentXML()
{
...
var query = ParseObject.GetQuery("RANDOM_TABLE").WhereEqualTo("some_field", "string");
var count = await query.CountAsync();
ParseObject temp_A;
temp_A = await query.FirstAsync();
...
// do lots of stuff
...
await temp_A.SaveAsync();
}
To summarize; A query is made to a remote database. From the result a specific object (or its reference) is obtained from the database. Multiple operations are performed on the object and in the end, its saved back into the database.
All the database operations happen via await ParseObject.randomfunction() . Is it possible to call these functions in a synchronous manner? Or at least wait till the operation returns without moving on? The application is designed for maintenance purposes and time of operation is NOT an issue.
I'm asking this because as things stand, I get an error which states
The number of count operations in progress has reached its limit.
I've tried,
var count = await query.CountAsync().ConfigureAwait(false);
in all the await calls, but it doesn't help - the code is still running asynchronously.
var count = query.CountAsync().Result;
causes the application to get stuck - fairly certain that I've hit a deadlock.
A bit of searching led me to this question,
How would I run an async Task<T> method synchronously?
But I don't understand how it could apply to my case, since I do not have access to the source of ParseObject. Help? (Am using .NET 4.5)
I recommend that you use asynchronous programming throughout. If you're running into some kind of resource issue (i.e., multiple queries on a single db not allowed), then you should structure your code so that cannot happen (e.g., disabling UI buttons while operations are in flight). Or, if you must, you can use SemaphoreSlim to throttle your async code:
private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
public async Task UploadCurrentXMLAsync()
{
await _mutex.WaitAsync();
try
{
...
var query = ParseObject.GetQuery("RANDOM_TABLE").WhereEqualTo("some_field", "string");
var count = await query.CountAsync();
ParseObject temp_A;
temp_A = await query.FirstAsync();
...
// do lots of stuff
...
await temp_A.SaveAsync();
}
finally
{
_mutex.Release();
}
}
But if you really, really want to synchronously block, you can do it like this:
public async Task UploadCurrentXMLAsync();
Task.Run(() => UploadCurrentXMLAsync()).Wait();
Again, I just can't recommend this last "solution", which is more of a hack than a proper solution.
if the api method returns an async task, you can get the awaiter and get the result synchronously
api.DoWorkAsync().GetAwaiter().GetResult();

Is it possible to use same async method signature in C# 5.0 and be able to decide later how to execute such method

I want to use recent C# 5.0 async methods, however some specific way.
Consider following example code:
public abstract class SomeBaseProvider : ISomeProvider
{
public abstract Task<string> Process(SomeParameters parameters);
}
public class SomeConcreteProvider1 : SomeBaseProvider
{
// in this method I want to minimize any overhead to create / run Task
// NOTE: I remove here async from method signature, because basically I want to run
// method to run in sync!
public override Task<string> Process(SomeParameters parameters) {
string result = "string which I don't need any async code to get";
return Task.Run(() => result);
}
}
public class SomeConcreteProvider2 : SomeBaseProvider
{
// in this method, it's OK for me to use async / await
public async override Task<string> Process(SomeParameters parameters) {
var data = await new WebClient().DownloadDataTaskAsync(urlToRequest);
string result = // ... here we convert data byte[] to string some way
return result;
}
}
Now how I am going to use async methods (you can ignore fact that consumer actually ASP.NET MVC4 app in my case... it can be anything):
public class SomeAsyncController : AsyncController
{
public async Task<ActionResult> SomethingAsync(string providerId)
{
// we just get here one of providers I define above
var provider = SomeService.GetProvider(providerId);
// we try to execute here Process method in async.
// However we might want to actually do it in sync instead, if
// provider is actually SomeConcreteProvider1 object.
string result = await provider.Process(new SomeParameters(...));
return Content(result);
}
}
As you can see I have 2 implementations, each one will perform differently: one I want to run in async and do not block thread (SomeConcreteProvider2), while another one I want to be able to run in sync and do not create any Task object etc (which I fail to code in code above, i.e. I do create new Task here!).
There are questions already like How would I run an async Task<T> method synchronously?. However I don't want to run something in sync... I want to avoid any overhead if I know at code time (i.e. before runtime) that some methods implementations will NOT actually be async and will not need to use any threads / I/O completion ports etc. If you check code above, its easy to see that method in SomeConcreteProvider1 basically will construct some string (html), can do it very quickly at the same execution thread. However same method in SomeConcreteProvider2 will need to create Web Request, get Web Response and process it someway and I do want to make at least Web Request in Async to avoid blocking of whole thread during request time (may be quit long time actually).
So the question is: how to organize my code (different method signatures or different implementations, or?) to be able to decide how to execute method and avoid ANY possible overhead which caused for example by Task.Run(...) in SomeConcreteProvider1.Process method?
Update 1: obvious solutions (I think up some of them during question process), such as for example to add some static property to each of providers (say 'isAsyncImplementation') and then check that property to decide how to run method (with await or without await in controller action) have some overhead too :D I want something better if possible :D
In your first case, I would recommend returning:
Task.FromResult(result)
which returns a ready-completed task.
http://msdn.microsoft.com/en-us/library/hh194922%28v=vs.110%29.aspx
Your design looks fine.
For the SomeConcreteProvider1 case, you can use a TaskCompletionSource
This returns a Task without requiring concurrency.
Also, in the consumer code, await will not yield if the Task has already completed. This is called the "fast path" and effectively makes the method synchronous.

Categories