So I was asking this question about async , and I thought that it it's just a sugar syntax for :
Task<..>...ContinueWith...
And finally inspect the Result property.
I even asked a question about it here and I was told :
But Today I was corrected by Jon Skeet
" It's a very long way from that".
So what are the core differences between those 2 approaches ?
It is adding a continuation - but manually constructing that continuation can be very painful, due to the need to carry around all the information about where we'd got to and what the local state is.
As a very simple example, I suggest you try to come up with the equivalent of this async method:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
// These are just examples - you don't need to translate them.
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Really try to come up with the equivalent of the first method. I think you'll find it takes quite a lot of code - especially if you actually want to get back to an appropriate thread each time. (Imagine code in that async method also modified a WPF UI, for example.) Oh, and make sure that if either of the tasks fails, your returned task fails too. (The async method will actually "miss" the failure of the second task if the first task also fails, but that's a relatively minor problem IMO.)
Next, work out how you'd need to change your code if you needed the equivalent of try/finally in the async method. Again, that'll make the non-async method more complicated. It can all be done, but it's a pain in the neck.
So yes, it's "just" syntactic sugar. So is foreach. So is a for loop (or any other kind of loop). In the case of async/await, it's syntactic sugar which can do really rather a lot to transform your code.
There are lots of videos and blog posts around async, and I would expect that just watching/reading a few of them would give you enough insight to appreciate that this is far from a minor tweak: it radically changes how practical it is to write large amounts of asynchronous code correctly.
Additionally, being pattern-based, async/await doesn't only work on Task / Task<T>. You can await anything which adheres to the awaitable pattern. In practice very few developers will need to implement the pattern themselves, but it allows for methods like Task.Yield which returns a YieldAwaitable rather than a task.
Related
I've been learning about HttpClient (consuming API's in .NET in general), and therefore about async programming. I'm still pretty lost right now, so trying to clear some things up. One question I can't seem to find an answer to - are asynchronous methods implemented exclusively using the async keyword?
I understand that you could (theoretically) create synchronous methods using async programming, but how do you recognize that? For example, from this link and this example:
public string GetReleases(string url)
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add(RequestConstants.UserAgent, RequestConstants.UserAgentValue);
var response = httpClient.GetStringAsync(new Uri(url)).Result;
return response;
}
}
The author says:
For the simplicity’s sake, I implemented it synchronously
But how do I recognize it is synchronous? Is it solely because the method is not defined with async Task, for example:
public async Task<string> GetReleases(string url)
Does that mean that in this HttpClient tutorial, this example is also not asynchronous:
// GET: Student
public ActionResult Index()
{
IEnumerable<StudentViewModel> students = null;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:64189/api/");
//HTTP GET
var responseTask = client.GetAsync("student");
responseTask.Wait();
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsAsync<IList<StudentViewModel>>();
readTask.Wait();
students = readTask.Result;
}
else //web api sent error response
{
//log response status here..
students = Enumerable.Empty<StudentViewModel>();
ModelState.AddModelError(string.Empty, "Server error. Please contact administrator.");
}
}
return View(students);
}
So to sum up, my questions are:
Is async programming (in .NET), and async methods, implemented exclusively using async and void/Task/Task?
If not, how else, and if so, how do I recognize "true" asynchronous methods compared to synchronous methods implemented using asychronous principles (like the example above?)
Why then did the above examples use "sync through async", since from everything I've read everyone says to NEVER do that? Are they just bad examples, or for simplicity sake (even so, shouldn't "the correct way" > "simplicity"? Would it be ok to use this in situations where, e.g., I have very simple code and want to avoid threading/deadlock issues, since I'm not comfortable with async programming just yet?
how can I recognize truely async/sync methods?
You can't. Not really. You can spot methods that are potentially async, but little else can be learned without consulting documentation or the implementation of those methods.
So, you can examine a method's return type. If it's void, you don't know much. If it's Task, Task<T>, ValueTask<T> or any other awaitable type1, then the method may be asynchronous. But bear in mind, the method signature may be fixed because the type inherited the method from a base class or it's implementing an interface; So whilst the method has the potential to be async, the actual implementation of that method may be completely synchronous.
Or, the method may have the potential to be asynchronous but may have particular control flows which lead to it behaving synchronously2. These may be e.g. that if certain conditions are true, the method already has the answer, so it returns it straight away. Otherwise it goes off and does something async - as one example.
If the return type isn't awaitable and it's non-void, all you can actually reason about the method is that, at the point at which it returns, it's supplied some value for that return type3. There's no way to reason about any other work that may have been started by that method - only that if it's done something like that, it doesn't intend for you to be able to discover when that work has completed.
If you're looking at the implementation of a method and asking yourself "is this implementation async" then the important thing is to work out what this code makes happen after control is returned back to the caller.
When is control returned back to the caller?
When we hit a return
When we hit an await, maybe
When we hit an await, we only return control back to the caller4 if the awaitable that we're awaiting isn't complete yet. So we have to find out where that awaitable came from and, if it came from calling another method, we have to start again from scratch in considering what that method does.
If the method contains awaits then it's usually safest to say that it's potentially async - but bear in mind the above possibilities about already completed awaitables and early returns.
If it's not async/await, what else might it have done? Well, if it's working with Tasks, it may have created one or more of those tasks to represent it's ongoing work. It may have scheduled more code to run via ContinueWith.
If it's not working with Tasks directly, hasn't called something else that is potentially async, hasn't cause a new Thread to be created and isn't needlessly obfuscated, it's probably synchronous.
Would it be ok to use this in situations where, e.g., I have very simple code and want to avoid threading/deadlock issues, since I'm not comfortable with async programming just yet?
The sync over async patterns shown in the examples in your question are more prone to deadlocks than working with async/await. Why? Because they block the current thread waiting for other things to happen. But the current thread or resources that it has locked may be special - and the actual async tasks that it's invoked may need to gain access to that same thread/resource before they can complete. Classic deadlock.
1Awaitable is one of a number of places where C# uses "duck typing". If there's a method available (instance or extension) called GetAwaiter that returns a type with the right shape, it's awaitable. So despite the fact that you'll probably never see one, be aware that custom awaitables are possible in the language.
2"Hot path" optimizations come to mind.
3And out/ref parameters. Of course, if it has those it won't be an async method implemented via the async/await keywords but it may still have some asynchronous behaviour.
4If we've already yielded control back to the caller during an earlier await, we won't return control back to the caller at later awaits, but we'll be returning it to "something" that isn't our code.
If a method returns a Task or Task<T> (with exception to void in case of event handler) then it can be awaited and hence it can be asynchronous. async keyword is only an indication that it may await somewhere for another awaitable. Based on the control flow, async may return without actually awaiting anything.
Asynchronous programming is not a new thing, it has existed in many forms like callbacks, Invokes etc.
Examples you have provided are not using async await pattern properly. Microsoft has provided naming convention (Async Suffix) and Task<T>, Task as types for async programming. So if you see some method returning Task<T> or Task and Method name has suffix "Async" then you can consider it asynchronous. Although suffix thing is not required by compiler, it helps in differentiating it from its synchronous counterpart. (Read vs ReadAsync)
They are bad examples, those action should be marked as async and all the Async methods should be awaited for result. There can be an exception in some console program where main can't be async.
Please read Stephen Cleary blog on async await
An asynchronous method in C# can return void, Task or Task<T>, where void should be avoided in general because it cannot be awaited.
As a convention asynchronous methods should be called DoSomethingAsync()
The async keyword, however, is an implementation detail and does not belong to the API. This keyword is only required if you use an await in the method body. But that need not be the case. You could simply delegate to another asynchronous method, without the need to mark the method as async and using an await.
So 'true' asynchronous methods should be recognizable by the Async suffix of the method name, however, you can't be sure the implementor actually uses naturally asynchronous operations or even runs synchronously some parts or the whole method.
In the example he made the method synchronously by putting .Result at the end of GetStringAsync
I have been researching how to convert my (synchronous) algorithms into asynchronous ones. (TAP)
First, just to be clear, this question is not about "what is Async and Await does" ( I already have read the excellent posts of Stephen Cleary , for example Async and Await (If anyone is interested read the link- it is very informative)
I have also read already the chapter on concurrency of "C# in a nutshell".
This question is not about how async functions use await to call functions either. I already know that.
Unfortunately in almost all the things I read, the await Task.Delay(10) is used to "make a asynchronous function". For example:
public async Task<int> GetResult()
{
int result= await GiveMeTheInt();
}
public async Task<int> GiveMeTheInt() //<--is async needed here? (oops! I just realize it is...
{
await Task.Delay(100);
return(10);
}
In this example for instance I already understand the magic of async await in the GetResult() function but the implementation of GiveMeTheInt() is not very useful.(They just put a Delay as a generic asynchronous function and leave it at that)
So my question is about the "GiveMeTheInt"-type of questions (not the ones who call them).
The question
If I have an algorithm written in a function that so far has been synchronous, how can I convert this to be used asynchronously?
This is not a duplicate question, the closest I have found is Turning a Syncronous method async in which the poster is told to use a async version of his method that already exists. In my case, this does not exist.
My algorithms consist mainly of Image processing so in essence scanning a large array and changing the values of each pixel. Something like
void DoSomethingToImage(int[,] Image)
{
for(int i=0;i<width;i++)
for(int j=0;j<height;j++)
{
Image[i,j]=255;
}
}
(This is a fictional example, the operation is different of course)
The closest I have gotten an answer to this is to put the function inside a Task.Run() but I am not sure if this is the way to do it.
Any help will be greatly appreciated
So take a look at your method:
void DoSomethingToImage(int[,] image)
{
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
image[i, j] = 255;
}
}
}
Is this asynchronous? Obviously not. This is just CPU-bound work that will keep the processor busy for a bit. As such, it is not a good candiate to make asynchronous on its own. It should be run synchronously.
What if you are consuming this from an asynchronous part of the application? You certainly don’t want the user interface to block because you are iterating through a lot of pixels. So the solution is to load the work off to another thread. You do that using Task.Run:
await Task.Run(() => DoSomethingToImage(image));
So you would write that whenever you call the DoSomethingToImage method from an asynchronous method. Now, if you only use that method inside asynchronous contexts, you could argue that it might make sense to move the Task.Run into the function:
Task DoSomethingToImageAsync(int[,] image)
{
return Task.Run(() => { … });
}
Is this a good idea? In general no, because now you are making the method look asynchronous when it’s in fact not. All it does is spawn a new thread that does the work, and then it waits for the thread to complete. So now you are hiding that part and also make a method doing highly synchronous work decide that a thread should be started. That’s rarely a good idea. And there is nothing wrong with keeping the method as it is, to show that it’s synchronous, and make the calling code responsible of deciding how that code should be run.
If I have an algorithm written in a function that so far has been synchronous, how can I convert this to be used asynchronously?
So, coming back to your actual question, this is actually difficult to answer. The answer is probably just this: “It depends”.
If a method does CPU-bound work, you’re better off keeping it synchronous and let calling code decide how to run it. If you are doing mostly I/O work where you interact with other interfaces (network, file system, etc.), then that’s a good candidate for making it asynchronous, especially considering that many of those interfaces will already offer asynchronous ways to communicate with them.
One final note regarding your “is async needed here?” question in your code: You need the async keyword whenever you want to use await inside of it. The mere presence of the async keyword does not make a method asynchronous though (not even the return type does indicate that).
I have a async method returning a task. Do I need to return anything in the following situation?
public async Task UpdateProductSpecificationsAsync()
{
await _productRepository.UpdateProductSpecificationsAsync(); //Takes long time to execute
}
Is the following code examples equivalent to each other?
public Task UpdateProductSpecifications()
{
_productRepository.UpdateProductSpecifications(); //Takes long time to execute
return Task.FromResult(0);
}
public Task UpdateProductSpecifications()
{
_productRepository.UpdateProductSpecifications(); //Takes long time to execute
return Task.CompletedTask;
}
Is there any situation where I should await a Task.TaskCompleted?
I have a async method returning a task. Do I need to return anything in the following situation?
An async Task method is equivalent to a non-async void method. And like a non-async void method, an async Task method can't return anything.
That said, your example seems odd. If all you're going to do in the method is await some other async method, you should not bother with the async/await at all. Just return the Task directly:
public Task UpdateProductSpecificationsAsync()
{
return _productRepository.UpdateProductSpecificationsAsync();
}
Is the following code examples equivalent to each other?
Define "equivalent". To me, they are definitely not equivalent. The first creates a new Task<int> object, and returns that object as a Task. Calling code would have to cast it back to Task<int> to see the result value.
The second returns the static Task.CompletedTask property value, which is a singleton object, allocated only once per process. There is no result value for the caller to read.
The caller would have to go to extra work to directly observe those differences, but at the very least, returning a reference to a singleton object is more efficient than creating a new object every time. Whether this is significant or not depends, of course, on how often you call the method.
All that said, I don't understand why in that scenario, you wouldn't implement it like this (assuming there's no truly asynchronous version of the _productRepository method):
public Task UpdateProductSpecificationsAsync()
{
return Task.Run(() => _productRepository.UpdateProductSpecifications());
}
Then you'd get actual asynchronous behavior, which is what the caller would typically expect. Your versions force the caller to wait in spite of the method looking like it's asynchronous. IMHO, it's a very bad idea to write code that lies.
Is there any situation where I should await a Task.TaskCompleted [sic]?
You mean directly? Or by code that doesn't know it's been handed the Task.CompletedTask reference? I'm going to assume the former, because it's unreasonable to expect the latter to have any idea that's what it's doing.
That seems like an overly broad question to me. Any situation? That's open to interpretation.
That said, I would say "no" to that question. What would the point of awaiting something you know is already completed? The await won't yield back to the caller, because the awaitable is already completed. It seems like a waste to me.
I can imagine scenarios where one awaits a Task.CompletedTask in order to achieve some other desired side-effect. I've seen weirder things than that in production code. But I wouldn't recommend it. Whatever hypothetical side-effect we'd be talking about, I'm sure it's not a documented side-effect, so one would be relying on undocumented implementation details that could change in the future.
Don't write fragile code. Write code that relies only on documented behavior, and only does things that make obvious sense. (And the corollary: if you break that rule, at the very least write a very detailed comment explaining why you wrote weird, fragile code.)
I'm a bit new to async coding with C#, and have encountered a few places where methods I have to implement (either from an interface or part of an inherited service, or just suggested default convention) are marked async and expect a Task<T> return.
But I don't always have async code to run; I don't always have something that needs an await operator.
So my ad-hoc workaround is to just return await Task.FromResult({normal code}); to these kinds of methods, like this...
public async Task<JsonResult> Id() {
// if the user is not authenticated, simply return false
if (!User.Identity.IsAuthenticated || String.IsNullOrEmpty(User.Identity.Name))
return await Task.FromResult(Json(false));
return await Task.FromResult((Json(User?.FindFirst("users/id")?.Value ?? null)));
}
This does solve the compile time errors, but I was wondering if there is an inherit problem with doing this. If so, what are good methods for getting around things marked as async that I cannot change?
Rather than creating a Task, then adding a continuation to that task that does literally noting but wrap it in an identical Task, just return the first task that you created.
Since you have nothing to await, there is no reason for the method to be marked as async.
Considering the performance costs of FromResult is a pointless discussion. You need to create a task based on the result that you have, so that work needs to be done. Considering how expensive it is is irrelevant as you have no alternative options. You could try to create your own FromResult method if you think you can write one that'll perform better than Microsoft's version.
That said, no, it is not particularly expensive of an operation.
Now, there's a 99% chance that this "nitpick" I have found is entirely due to my own ignorance - I'm a junior web developer who has only been exposed to C# sporadically for a couple of months, so I apologize in advance for the probable stupidity of my question. Most of my experience is with PHP and JS.
If I have a method declared with the async keyword as such:
public async Task<ActionResult> Create(MyObject myObject)
{
}
Why do I also have to specify that LINQ statements be asynchronous explicitly like so:
public async Task<ActionResult> Create(MyObject myObject)
{
if (ModelState.IsValid)
{
myObject.Id = Guid.NewGuid();
myObject.DisplayId = await db.MyObjects.MaxAsync(m => m.DisplayId) + 1;
db.MyObjects.Add(myObject);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(myObject);
}
Can't the C# compiler be clever enough to figure out that because the method is asynychronous, the LINQ statements I want to execute within the method should be asynchronous too?
I guess my real beef with this is that there's now an asynchronous twin for most LINQ methods (SaveChangesAsync, MaxAsync, FirstOrDefaultAsync), and I have to use the await keyword every time I want to execute such calls. It seems excessively verbose and unnecessary.
If granular control over the synchronicity of the call was still needed, why didn't the C# developers simply allow for an .Await(),.Async(), or Sync() method that I could append?
Can't the C# compiler be clever enough to figure out that because the method is asynychronous, the LINQ statements I want to execute within the method should be asynchronous too?
What if you want to make a synchronous call in an asynchronous method?
Do you want the same method to be synchronous or asynchronous depending on whether or not you're in an asynchronous method? I guess it would be possible for a language to do that, but it would require a fundamentally different model that is not the one used by C#. Also, I'm not sure it would be a good idea; it could be pretty confusing. Better to make things explicit IMO.
I guess my real beef with this is that there's now an asynchronous twin for most LINQ methods (SaveChangesAsync, MaxAsync, FirstOrDefaultAsync), and I have to use the await keyword every time I want to execute such calls. It seems excessively verbose and unnecessary.
Using await or not doesn't have the same meaning. If you don't use await, you just retrieve the task, which can be useful in some scenarios (e.g. if you want to parallelize tasks. For instance, consider the following:
Task t1 = SomeAsyncOperation();
Task t2 = SomeOtherAsyncOperation();
await Task.WhenAll(t1, t2);
In the code above, the operations run in parallel. Now, if you use await on each call:
await SomeAsyncOperation();
await SomeOtherAsyncOperation();
The operations are now sequential.
The developer needs to be in control of this kind of thing. That's why the await cannot be implicit, because it changes the behavior of the code.
If granular control over the synchronicity of the call was still needed, why didn't the C# developers simply allow for an .Await() or .Async() method that I could append?
How would a .Await() method be better than a keyword? Anyway, it wouldn't work. The use of the await keyword transforms the body of the method into a state machine; a method call can't do that.
await completely changes the way code for the method is generated - state machine vs. linear code - so you can't magically implement it with any custom .Await() method because method calls compiled into linear code.
C# generally chooses explicit approach vs. magically guess intentions - so while there are cases when compiler may guess need for await call it does not.
Note that with var it frequently impossible to make a guess either:
var displayId = db.MyObjects.MaxAsync(m => m.DisplayId);
displayId could be Task or if compiler allowed to guess for missing await it could be int.