I'm currently trying to write async code and I have the feeling that my code is not too correct at all.
I have the following method:
public void Commit()
{
_context.SaveChangesToDatabase();
}
Don't judge the code here as this are only samples. Also, don't say that if I'm using Entity Framework, that they come packaged with Async methods already. I just want to understand the async concept here.
Let's say that the method SaveChangesToDatabase does takes seconds to complete.
Now, I don't want to wait for it so I create an async method:
public async Task CommitAsync()
{
await Task.Run(() => Commit());
}
Does this mean that if I have a method:
public void Method()
{
// Operation One:
CommitAsync();
// Operation Two.
}
Does this mean that my code on Operation two will be executed before CommitAsync() is even completed?
If not, please guide me in the right direction.
Update
Based on the remarks here that I'm ignoring my async method results, is this implementation better?
public Task<TaskResult> CommitAsync()
{
var task = new Task<TaskResult>(() =>
{
try { Commit(); }
catch (Exception ex)
{
return new TaskResult
{
Result = TaskExceutionResult.Failed,
Message = ex.Message
};
}
return new TaskResult { Result = TaskExceutionResult.Succeeded };
});
task.Start();
return task;
}
This does mean that I need to put the async modifier on the method that call this code so that I can await this which means continue with the current execution and return when this method has been completed.
Fire but don't forget
CommitAsync() returns a Task, but Method ignores the return value of CommitAsync completely -- so yes, the code will not wait but simply go on with what's after that. This is bad, because, if Commit() throws an exception, you will never see it. Ideally, every task should be waited on somewhere by someone, so you can at least see if it fails.
Let's say that you have no async alternative to SaveChangesToDatabase, but you'd like to use it in an async context anyway. You can use Task.Run to create a "fake-asynchronous" method, but this is not recommended (see below):
public Task CommitAsync() {
return Task.Run(() => Commit());
}
And then, assuming Method is doing something interesting with async (which the below code does not do since it's the only asynchronous operation in there):
public async Task MethodAsync() {
// Operation One:
await CommitAsync();
// Operation Two.
}
Assuming you do not want to wait, but you do want to do something if the task failed, you can use a separate method:
public void Method() {
// Operation One:
var _ = TryCommitAsync();
// Operation Two.
}
private async Task TryCommitAsync()
{
try
{
await CommitAsync();
}
catch (Exception ex)
{
Console.WriteLine(
"Committing failed in the background: {0}",
ex.Message
);
}
}
Getting back results
Let's suppose .Commit() does return something (like the number of records affected); a similar "fake-asynchronous" wrapper (again, not recommended - see below) would look like this:
public Task<int> CommitAsync() {
return Task.Run(() => Commit());
}
If you want this result, you can await the task immediately:
public async Task MethodAsync() {
// Operation One:
int recordsAffected = await CommitAsync();
// Operation Two.
}
Or, if you don't need it immediately, use await when you do:
public async Task MethodAsync() {
// Operation One:
Task<int> commit = CommitAsync();
// Operation Two.
// At this point I'd really like to know how many records were committed.
int recordsAffected = await commit;
}
Async: don't fake it
In general, you don't want to write wrappers like CommitAsync() because they mislead callers into thinking code will be asynchronous when it isn't really, which brings few benefits other than not blocking (which is still useful in UI code, but not as good as true asynchronous code which doesn't need to use worker threads for everything). In other words, you should use Task.Run in the invocation of a method, not as the implementation of a method.
So don't, as a habit, write wrappers like CommitAsync for every synchronous method you have -- instead you want to make a true CommitAsync that uses the async support of the underlying libraries/frameworks (SqlCommand.ExecuteReaderAsync(), etcetera.)
If you have no choice and must use Task.Run, then the appropriate usage would look more like:
// This method is in the UI layer.
public async Task MethodAsync() {
// Operation One:
// Commit() is a method in the DA layer.
await Task.Run(() => Commit());
// Operation Two.
}
Here
http://channel9.msdn.com/events/TechEd/NorthAmerica/2013/DEV-B318#fbid=
is a good explanation on how to work with async, and why you should avoid "async over sync", which is what you are doing now with
public Task CommitAsync() {
return Task.Run(() => Commit());
}
There are some scenarios where you can benefit from it, but if you are going to provide this as part of a library is NOT a good idea to make this.
If this code is ONLY and ONLY going to be used by your app, and you are sure what you are doing and dont have a wawy to call async methods inside your async method, just do it
Related
This question already has answers here:
Any difference between "await Task.Run(); return;" and "return Task.Run()"? [duplicate]
(4 answers)
Closed 8 years ago.
Is there any difference between the methods below? Is one preferable over the other?
public static async Task SendAsync1(string to, string subject, string htmlBody) {
// ...
await smtp.SendMailAsync(message);
// No return statement
}
public static Task SendAsync2(string to, string subject, string htmlBody) {
// ...
return smtp.SendMailAsync(message);
}
This method will be called from MVC controller methods; for example:
public async Task<ActionResult> RegisterUser(RegisterViewModel model)
{
// ...
await Mailer.SendAsync(user.Email, subject, body);
return View(model);
}
There are 2 practical differences:
The second option will not create the state machine mecanism that allows for async-await usage. That will have a minor positive effect on performance.
The exception handling would be a little different. When you mark a method as async any exceptions are stored in the returned task (both from the asynchronous part and the synchronous one) and thrown only when the task is awaited (or waited). When it's not async, the exceptions from the synchronous parts act just like in any other method.
My suggestion: Use the second one for the added performance boost but keep an eye out for exceptions and bugs.
An example that shows the difference:
public static async Task Test()
{
Task pending = Task.FromResult(true);
try
{
pending = SendAsync1();
}
catch (Exception)
{
Console.WriteLine("1-sync");
}
try
{
await pending;
}
catch (Exception)
{
Console.WriteLine("1-async");
}
pending = Task.FromResult(true);
try
{
pending = SendAsync2();
}
catch (Exception)
{
Console.WriteLine("2-sync");
}
try
{
await pending;
}
catch (Exception)
{
Console.WriteLine("2-async");
}
}
public static async Task SendAsync1()
{
throw new Exception("Sync Exception");
await Task.Delay(10);
}
public static Task SendAsync2()
{
throw new Exception("Sync Exception");
return Task.Delay(10);
}
Output:
1-async
2-sync
First of all, I don't think that the code in your example compiles. You need to remove the 'async' keyword from SendAsync2.
If you do that, then these methods can be used interchangeably, so no, there is no difference in this case. I would prefer the one without async/await.
However, there are cases where it would seem that there is no difference, but the difference lies in the details. Consider for example this code:
async Task<X> Get()
{
using (something)
{
return await GetX();
}
}
If you were to change this to:
Task<X> Get()
{
using (something)
{
return GetX();
}
}
then the using block no longer protects the execution encapsulated in x, and something will be disposed earlier than it would in the first case. Important for example when something is a Entity Framework context.
The same goes for return await inside try blocks.
Your first method which awaits will cause the compiler to create a state machine, since once the await keyword is hit the method will return to the caller, and once the awaited part is completed it has to resume from the point where it left off.
But, since you aren't doing anything after awaiting (there is no continuation), there is no need for that state machine.
The second method is preferred in this case, and you can omit the async keyword from it since you are not awaiting anything
I've been banging my head against a wall for two days now, and frankly I'm annoyed with myself because I just can't seem to get it.
I'm in a webapi context. During this request I need to send some data to one of our other systems, this system is slow to return, due to heavy calculations and multiple database saves etc etc. I need to log the result of this operation, regardless of whether it is successful or not. But I don't want to wait around for it to finish.
I've read that I should be async await all the way from top to bottom. I would have to convert numerous methods if I decided to do this, as I'm already 3 or 4 methods deep, which I fear would branch out even more.
What are my options here? If I go async await all the way down, what do I do with the methods higher up the stack, like my WebApi controllers?
Here is my code, I've tried to thin it down as much as I can. Right now I'm using Task.Result() in the method PushResult(). Which to my understanding is blocking the async? This code works in that the request gets sent. But the TestLog is always last, not first. Therefore not async.
//I'm in a public service and referenced twice
private void MyEndProcess()
{
// other stuff
_vendorPushService.PushResult(); // This could take a while and I have to wait for it!
_logService.PostLog(LogType.TestLog, "Test");
}
//I'm referenced above and somewhere else in the code base
public void PushResult()
{
ExternalResultModel externalResultModel = _resultService.GetExternalResultModel();
PushedResultModel pushedResult = new PushedResultModel();
try
{
pushedResult = _vendorRequestService.PushResultAsync(externalResultModel).Result;
}
catch (Exception ex)
{
pushedResult.Success = false;
}
if (pushedResult.Success)
{
_logService.PostLog(LogType.SuccessLog, pushedResult.Message);
}
else
{
_logService.PostLog(LogType.FailedLog, pushedResult.Message);
}
}
public async Task<PushedResultModel> PushResultAsync(ExternalResultModel externalResultModel)
{
// setup the requestMessage
HttpResponseMessage responseMessage = await _httpRequestService
.SendRequest(requestMessage)
.ConfigureAwait(false);
return new PushedResultModel
{
Success = responseMessage.IsSuccessStatusCode,
Message = await responseMessage.Content.ReadAsStringAsync()
};
}
public class HttpRequestService : IHttpRequestService
{
private readonly HttpClient _httpClient;
public HttpRequestService(IHttpClientAccessor httpClientAccessor)
{
_httpClient = httpClientAccessor.HttpClient;
}
public async Task<HttpResponseMessage> SendRequest(HttpRequestMessage requestMessage)
{
HttpResponseMessage httpResponseMessage = await _httpClient.SendAsync(requestMessage).ConfigureAwait(false);
return httpResponseMessage;
}
}
You should implement async await all the way from top to bottom.
If I go async await all the way down, what do I do with the methods higher up the stack, like my WebApi controllers?
Just make your controller actions async like this:
[RoutePrefix("api")]
public class PresidentsController : ApiController
{
[Route("presidents")]
public async Task<IHttpActionResult> GetPresidents()
{
await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);
return Ok();
}
}
It's easiest way to implement async methods. Even if it will add some work to change everything to async it will benefit in future, because You will avoid many problem with async code.
If you absolutly HAVE to use async method in synchronous methods make it block in ONE place, like this:
public void MySyncMethod()
{
try
{
this.MyAsyncMethod().Wait();
}
catch (Exception exception)
{
//omited
}
}
private async Task MyAsyncMethod()
{
await AsyncLogic().ConfigureAwait(false);
}
But i don't recommend it. You should just use async await all the way to controller action.
In your comment you said you want to process a task in the background and not make the client calling your API wait. To do that, you don't really need to use async/await.
Try this:
private void MyEndProcess()
{
// other stuff
Task.Run(_vendorPushService.PushResult()).ConfigureAwait(false); //fire and forget
_logService.PostLog(LogType.TestLog, "Test");
}
The Task.Run will start the task, and the ConfigureAwait(false) tells it that it does not need to resume on the same context that we're currently on (meaning that the context can close before the task is finished - i.e. the response can be sent back without waiting for the task to finish).
You will get a compiler warning that you're not awaiting Task.Run, but that's what you want.
Keep in mind that when you do this, HttpContext.Current will not be available inside PushResult.
I've followed the following example which works well.
https://developer.xamarin.com/guides/cross-platform/application_fundamentals/web_services/walkthrough_working_with_WCF/
The only issue is, the example uses button clicks to load data. Now i have two separate calls different functions, and i need one to wait for the other, for example:
So when i call function2 for example, i want to wait for function1 first.
_client.function1Async();
_client.function2Async();
I could put the function2 call inside the function1Completed handler, but i was looking to use async wait with it. When i use async task, i get an error saying cannot await a void. But the web service async function in the example is a void
If i had 6 calls that i wanted to run, it would become very messy.
void _client_function1Completed(object sender,UpdateOrdersByWardCompletedEventArgs e
{
}
void _client_function2Completed(object sender,UpdateOrdersByWardCompletedEventArgs e
{
}
Hope this makes sense.
You could Task.ContinueWith
ContinueWith creates a continuation that executes asynchronously when task 1 completes.
var task1 = Task.Factory.StartNew( () => { func1(); } );
Task task2 = task1 .ContinueWith( (i) => { func2(); } );
Not sure if I understood well what you are trying to achieve, but I guess you can try something like this:
Given some lengthy (and blocking) methods:
public void func1()
{
Console.WriteLine("func1");
System.Threading.Thread.Sleep(5000);
}
public void func2()
{
Console.WriteLine("func2");
System.Threading.Thread.Sleep(5000);
}
You could add the ability to run the lengthy stuff asynchronously by doing this:
public async Task function1Async()
{
await Task.Run(() => {
func1();
});
}
public async Task function1Async()
{
await Task.Run(() => {
func2();
});
}
Now you can choose to run 'func1' and 'func2' either asynchronously or synchronously, for example:
function1Async().Wait(); // will block
function2Async(); // will run asynchronously
So, for your particular case, given that you already have the two async methods, I guess that all you need to do is to call them as shown above.
I'm trying to troubleshoot an issue where we believe an Async call may not execute in some instances.
Would doWork() complete executing even after the controller has returned and no call to EndInoke()?
Is there another case where this would not execute, like an exception throw in doWork()?
delegate void TestDelegate();
void doWork()
{
Thread.Sleep(5000);
}
public ActionResult Test()
{
var myAsyncCall = new TestDelegate(doWork);
myAsyncCall.BeginInvoke();
return View();
}
In general, you need to call EndInvoke on the delegate. This will allow you to determine why things are not working (like an exception being raised within doWork, which would explain the described issue).
For details, see Calling Synchronous Methods Asynchronously on MSDN.
That being said, I would recommend reworking this to use the the TPL instead of delegate.BeginInvoke, as it makes some of the checking simpler overall. You could write the above as:
public ActionResult Test()
{
// Start the async work, and attach a continuation which happens if exceptions occur
Task.Run(() => doWork())
.ContinueWith(t =>
{
var ex = t.Exception.InnerException;
LogException(ex);
}, TaskContinuationOptions.OnlyOnFaulted);
return View();
}
I am using MvvmLight and have implemented communication between some of my ViewModels using the MessengerInstance.Send(...) method. It works great!
Recently, though, I have moved from using Synchronous methods to async methods to retrieve data and it looks like this breaks messaging (probably because it executes on a different thread). For example:
public ICommand SomeCommand { get { return new RelayCommand(DoSomething); } }
private async void DoSomething(object obj)
{
//Used to be SomeWcfService.DoSomething(); with some logic afterward
await SomeWcfService.DoSomethingAsync().ContinueWith(task => { //Some logic after method completes });
MessengerInstance.Send(SomeDataToSend, MessageIdentifer.DoSomething);
}
Instead of using a continuation, just put it after the await:
private async void DoSomething(object obj)
{
//Used to be SomeWcfService.DoSomething(); with some logic afterward
var result = await SomeWcfService.DoSomethingAsync();
// .ContinueWith(task => { //Some logic after method completes });
// use result here!
MessengerInstance.Send(SomeDataToSend, MessageIdentifer.DoSomething);
}
If there is no result returned from DoSomethingAsync, you can just leave out the result, and put your code in place.
The continuation, as you wrote it, will not run on the same synchronization context. The await keyword is actually asynchronously waiting your continuation, not the async method from WCF, as well.
If your "some logic" is asynchronous, you can use await within that code, as well.