Changing previous synchronous method to asynchronous - c#

I have a method called from within a program that authorizes card payment which was previously implemented in a synchronous way. However now I want to change it so it runs on a different thread so I can send cancel request once it has started.
It works, but I want to know if this is a good implementation, if there are some things I need to consider like deadlocks etc.
So here is a simplified version of my code:
public void Authorize()
{
lock(object)
{
AuthorizeAsync();
}
}
public async void AuthorizeAsync()
{
// ...
IProgress<string> progressHandler = new Progress<string>(progressString =>
{
UpdateProgressWindow(progressString.ToString());
});
cancellationToken = progressWindow.CancellationTokenSource.Token;
progressWindow.show();
results = await DoAuthorizeAsync(progressHandler, cancellationToken).ConfigureAwait(false);
// ...
}
I mainly want to use async - await because I want the authorization work to run separately from the UI thread so the user can still cancel the operation.
Do you suggest another approach other than async - await?
I am mainly concerned with the fact that I am calling an async method from sync method, I know the best practice is to use async all the way up but I cannot change the rest of the program.
The other concern I have is the lock in Authorize() could it pose any problem? I only want the code to be accessed by one thread at a time.
I am fairly new to this async - await architecture in .net so I'm pretty sure I didn't get it right on my first attempt.

Related

C# ASP.NET Core API Async/await VS Result

I'm a bit confused on best practices with c# and tasks.
When I was taught c# and tasks it was always an async function that awaits a task. But recently I have been doing some research and found some people who say otherwise. They also say that limiting usage of async and await can improve performance and Ram usage.
For example in This Stackoverflow post It says you shouldn't always await every task but the example isnt for an ASP.NET API and there isn't any previous data used to get the new data.
This post also is in favor of not always awaiting every task. But again the example is a simple task being passed through.
So my question is for cases when there is another task on which the second task must wait. Can you use .Result or is it better us use async/await. Because I heard .Result is blocking the current thread.
But I can't see how the current thread would not be blocked by the await since the output of the first statement is needed for the second statement.
Example without async/await
public Task<User> SaveUser(User user)
{
var dbUser = _userRepository.GetByUid(user.Id).Result;
if(dbUser == null) {
dbUser = new User();
dbUser.Id = Guid.NewGuid();
}
dbUser.Name = user.Name;
return _userRepository.Save(dbUser);
}
Example with async/await
public async Task<User> SaveUser(User user)
{
var dbUser = await _userRepository.GetByUid(user.Id);
if(dbUser == null) {
dbUser = new User();
dbUser.Id = Guid.NewGuid();
}
dbUser.Name = user.Name;
return await _userRepository.Save(dbUser);
}
Note: I also heard that when using an UI, it's important that UI related tasks are awaited but this would be for API's.
I recommend reading my async intro and following up with my post on eliding async and await. TL;DR: use async/await by default, and only elide them when the method is a simple passthrough method. Since your example is not a simple passthrough method, you should keep the async/await keywords.
It's also important to draw a distinction between "asynchronous" and async. There are several kinds of asynchronous code, whereas async is an implementation detail - one specific kind of asynchronous code. Both of the methods in your question are asynchronous, but only one uses async.
They also say that limiting usage of async and await can improve performance and Ram usage.
Yes, by removing the state machine overhead of the async keyword. However, this also removes all the benefits of the state machine, so you should only remove async on simple passthrough methods.
Can you use .Result or is it better us use async/await. Because I heard .Result is blocking the current thread.
You should use async/await whenever possible, and avoid Result, even on ASP.NET Core.
But I can't see how the current thread would not be blocked by the await since the output of the first statement is needed for the second statement.
The thread is not blocked. await works by sticking a bookmark in the method and then returning a result. So the thread is not blocked, but you can think of the method as "paused". https://blog.stephencleary.com/2012/02/async-and-await.html

Is async method synchronous if await Task is never returned?

I have a constructor that is called on UI thread in my WPF app. Inside of it, it calls async method but it must be done in a synchronous way. So I tried to call wait, but it caused deadlock an I understand why. So I introduced argument that indicates if method should be run in a asynchronous or synchronous manner. Something like this:
// constructor that is called on UI thread
public MyClass()
{
Method1(false).Wait();
}
public async Task Method1(bool runAsync)
{
await Method2(runAsync);
}
public async Task Method2(bool runAsync)
{
if (runAsync)
{
await Task.Run(() => Thread.Sleep(1000));
}
else
{
Thread.Sleep(1000);
}
}
I don't want to use ConfigureAwait because I want everything to run on UI thread. Will Method1(false).Wait(); ever cause a deadlock (is it safe to use)? I tested it a lot and it didn't, but I'm not sure. Finally, my real question is: if 'await Task.Run(...' is never executed, is my method completely synchronous? I found several posts on this subject, but none of them answers directly to my question.
I have a constructor that is called on UI thread in my WPF app. Inside of it, it calls async method but it must be done in a synchronous way.
I'm gonna stop you right there. The best solution is not to run synchronous/blocking code on the UI thread. That degrades your user experience. Instead, you should restructure your code so that you're never in this situation in the first place.
When a UI is being shown, the UI framework asks your code for the data to display. Your code should run synchronously and return immediately (not blocking). But your code also needs to do some asynchronous work in order to have the data to display. So there's a conflict there.
The solution is to design an intermediate state for your UI, e.g., a "loading..." message or a spinner. Then, when your code starts, it can synchronously/immediately display the "loading" state (and start the asynchronous operation), and when the asynchronous data arrives, the code updates the UI to the "final" state.
I discuss this pattern in more detail in my article on async MVVM data.
Instead of wrestling with async stuff at construction (your blocking solution isn't so good), why not write an async factory to spew out these objects?
class MyClass
{
public MyClass()
{
}
public async Task Method2(bool runAsync)
{
//async immediately
await Task.Delay(1000); //no Thread.Sleep. Blocking code != good
}
}
then
public MyClassFactory
{
public async Task<MyClass> GetAsync()
{
var c = new MyClass();
await c.Method2();
return c;
}
}

Where to use Task.Run if using a library does not support async await

I have an application which sends a message over the network, and I would like to perform other work while waiting for the message to be sent and responded to. I start the messaging process by calling "await SendMessageAsync", which has the following duties:
public async Task<bool> SendMessageAsync()
{
//Do Some Work
//Send First Message
//More Work
//Send Second Message
//More Work
//Send Third Message
}
If my third party library supported it, I would write it like this:
public async Task<bool> SendMessageAsync()
{
//Do Some Work
await LibrarySendMessageAsync(firstMessage);
//More Work
await LibrarySendMessageAsync(secondMessage);
//More Work
await LibrarySendMessageAsync(thirdMessage);
}
However SendMessageAsync is not working properly with timeouts. So I'll need to introduce some parallelism and use Task.Run.
My question is: would it be better to wrap the entire above method in Task.Run, or to wrap each SendMessage method in its own Task.Run?
public async Task<bool> SendMessageAsync()
{
//Do Some Work
await Task.Run(() => LibrarySendMessage(firstMessage));
//More Work
await Task.Run(() => LibrarySendMessage(secondMessage));
//More Work
await Task.Run(() => LibrarySendMessage(thirdMessage));
}
VS
public async Task<bool> SendMessageAsync()
{
await Task.Run(() =>
{
//Do Some Work
LibrarySendMessage(firstMessage);
//More Work
LibrarySendMessage(secondMessage);
//More Work
LibrarySendMessage(thirdMessage);
});
}
Performance (speed) is very important for this application. SendMessageAsync will be called repeatedly in a high frequency.
It depends.
Wrapping the whole thing in a single Task.run is logically simpler to reason with. Once the task is created, the three messages are sent synchronously. synchronous code is always simpler to write, read, and debug
It is more complicated when it comes to performance. In both cases, the 3 messages are sent in an ordered sequence.
Three Task.Runs consume less thread(thread is returned faster to the pool) but will create more tasks as well as incur the cost of transitioning from one task to another. A single task will cause the thread to block longer then necessary. You will need more threads in the thread pool to handle the same amount of messages. You will be balancing the cost of waking up the thread to continue execution and picking a task from the queue to continue execution.
The balance will depend on how long does sending the 3 messages take, how many thread pool thread you can afford to have, what will the expected through put be, and even the pattern of the message arrival(evenly vs sporadic). And, of course, eventually everything depends on profiling.
Basically your second option... you have a method :-
public async Task<bool> SendMessageAsync()
which basically shouldn't be async. You are saying basically you want the method to be synchronous.... so write that method
public bool SendMessage()
{
//Do Some Work
LibrarySendMessage(firstMessage);
//More Work
LibrarySendMessage(secondMessage);
//More Work
LibrarySendMessage(thirdMessage);
}
Don't write synchronous code as weird confused async method. So then if you you want to do that work in a thread then await...
await Task.Run(() => SendMessage());
which you can wrap into your original method SendMessageAsync

How can I understand where the final 'async' keyword goes in the tree of async-awaits? [duplicate]

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.

async Task<HttpResponseMessage> Get VS HttpResponseMessage Get

I would need your help in the following. For nearly a month, I have been reading regarding Tasks and async .
I wanted to try to implement my new acquired knowledege, in a simple wep api project. I have the following methods and both of them working as expected:
public HttpResponseMessage Get()
{
var data = _userServices.GetUsers();
return Request.CreateResponse(HttpStatusCode.OK, data);
}
public async Task<HttpResponseMessage> Get()
{
var data = _userServices.GetUsers();
return await Task<HttpResponseMessage>.Factory.StartNew(() =>
{
return Request.CreateResponse(HttpStatusCode.OK, data);
});
}
So the question. I have tried to use fiddler and see what is the difference between these two. The async one is little faster, but apart from that, what is the real benefit in implementing something like that in a web api?
As others have pointed out, the point of async on ASP.NET is that it frees up one of the ASP.NET thread pool threads. This works great for naturally-asynchronous operations such as I/O-bound operations because that's one less thread on the server (there is no thread that is "processing" the async operation, as I explain on my blog). Thus, the primary benefit of async on the server side is scalability.
However, you want to avoid Task.Run (and, even worse, Task.Factory.StartNew) on ASP.NET. I call this "fake asynchrony" because they're just doing synchronous/blocking work on a thread pool thread. They're useful in UI apps where you want to push work off the UI thread so the UI remains responsive, but they should (almost) never be used on ASP.NET or other server apps.
Using Task.Run or Task.Factory.StartNew on ASP.NET will actually decrease your scalability. They will cause some unnecessary thread switches. For longer-running operations, you could end up throwing off the ASP.NET thread pool heuristics, causing additional threads to be created and later destroyed needlessly. I explore these performance problems step-by-step in another blog post.
So, you need to think about what each action is doing, and whether any of that should be async. If it should, then that action should be async. In your case:
public HttpResponseMessage Get()
{
var data = _userServices.GetUsers();
return Request.CreateResponse(HttpStatusCode.OK, data);
}
What exactly is Request.CreateResponse doing? It's just creating response object. That's it - just a fancy new. There's no I/O going on there, and it certainly isn't something that needs to be pushed off to a background thread.
However, GetUsers is much more interesting. That sounds more like a data read, which is I/O-based. If your backend can scale (e.g., Azure SQL / Tables / etc), then you should look at making that async first, and once your service is exposing a GetUsersAsync, then this action could become async too:
public async Task<HttpResponseMessage> Get()
{
var data = await _userServices.GetUsersAsync();
return Request.CreateResponse(HttpStatusCode.OK, data);
}
Using async on your server can dramatically improve scalability as it frees up the thread serving the request to handle other requests while the async operation is in progress. For example in a synchronous IO operaton, the thread would be suspended and doing nothing until the operation completes and would not be available to serve another request.
That being said, using Task.Factory.StartNew starts another thread so you don't get the scalability benefits at all. Your original thread can be reused, but you have offloaded the work to another thread so there is no net benefit at all. in fact there is a cost of switching to another thread, but that is minimal.
Truly asynchronous operations do not start a thread and I would look to see if such an operation exists, or if one can be written for Request.CreateResponse. Then your code would be much more scalable. If not, you are better off sticking with the synchronous approach.
It makes more sense where the call is happening with major IO operations.
Yes, Async is faster because it frees up the request thread for the time that the operations is being performed. Thus, from Web server point of view, you are giving a thread back to the pool that can be used by the server for any future calls coming through.
So for e.g. when you are performing a search operation on SQL server, you might want to do async and see the performance benefit.
It is good for scalability that involves multiple servers.
So, for e.g. when the SearchRecordAsync sends its SQL to the database, it returns an incomplete task, and when the request hits the await, it returns the request thread to the thread pool. Later, when the DB operation completes, a request thread is taken from the thread pool and used to continue the request.
Even if you are not using, SQL operations, let say you want to send an email to 10 people. In this case also async makes more sense.
Async is also very handy to show the progress of long event. So user will still get the active GUI, while the task is running at the background.
To understand, please have a look at this sample.
Here I am trying to initiate task called send mail. Interim I want to update database, while the background is performing send mail task.
Once the database update has happened, it is waiting for the send mail task to be completed. However, with this approach it is quite clear that I can run task at the background and still proceed with original (main) thread.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Console.WriteLine("Starting Send Mail Async Task");
Task task = new Task(SendMessage);
task.Start();
Console.WriteLine("Update Database");
UpdateDatabase();
while (true)
{
// dummy wait for background send mail.
if (task.Status == TaskStatus.RanToCompletion)
{
break;
}
}
}
public static async void SendMessage()
{
// Calls to TaskOfTResult_MethodAsync
Task<bool> returnedTaskTResult = MailSenderAsync();
bool result = await returnedTaskTResult;
if (result)
{
UpdateDatabase();
}
Console.WriteLine("Mail Sent!");
}
private static void UpdateDatabase()
{
for (var i = 1; i < 1000; i++) ;
Console.WriteLine("Database Updated!");
}
private static async Task<bool> MailSenderAsync()
{
Console.WriteLine("Send Mail Start.");
for (var i = 1; i < 1000000000; i++) ;
return true;
}
}

Categories