I've read a lot of articles about asynchronnous programming, but I'm not sure in one thing. I have 3rd party winrt library, written in C++ and I want to wrapp it. So now I have:
public Task LoginAsync(){
return Task.Run(winrtLibrary.Login();)
}
According Stephen Cleary and Stephen Toub blogs, it is not good solution. But when I use the method synchronously, my UI will not be responsive and will be blocked.
Is it better to expose service method synchronously and in UI use Task.Run?
What Stephen Toub means by
do not use Task.Run in the implementation of the method; instead, use Task.Run to call the method
Is that you shouldn't use Task.Run to hide CPU bound work behind async methods (Task returning methods). If you need to wrap external code, hide it behind an interface which reflects what this code do. Any asynchronous I/O can (and should) be exposed as Task returning methods, and CPU bound work must be exposed with the proper API. Let the consumers of your code to decide for themselves how to use that code. When you happen to by the consumer too, use Task.Run to run your synchronous code (now wrapped and exposed via interface) where it is very clear that you are offloading CPU bound work. In UI apps, for example, you should call Task.Run in your UI layer (and not deep down in your BL or even DA layers), where it is very clear that the UI offloads some CPU bound work.
Why do you think, that I shouldn't call Task.Run in BL? What if I have
ViewModel, which references BL and BL references service layer (in my
case is it wrapper).
I think that a method signature should reflect exactly what the method does.
The best I can do is to redirect you back to Cleary's article:
When a developer sees two methods in an API winrtLibrary.Login() and winrtLibrary.LoginAsync(), the convention is that they represent a naturally-asynchronous
operation. In other words, the developer expects that winrtLibrary.LoginAsync() is
the “natural” implementation and that winrtLibrary.Login() is essentially a
synchronous (blocking) equivalent of that operation. That API implies
that winrtLibrary.Login will at some point have the calling thread enter a wait
state as it blocks for the naturally-asynchronous operation to
complete.
You can still hide synchronous code behind async method and follow Cleary's rule of thumb, if you sign your method as public Task OffloadLoginToTheThreadPool(). But I think (and apparently Cleary, too) that the alternative of simply calling Task.Run from the UI (or Controller) is a much better approach, and it follows the principles of Clean Code.
Related
I need to use a third-party DLL which implements a TCP socket client (in C++) using blocking calls. So basically (pseudocode);
void DoRequest()
{
send(myblockingSocket,data);
recv(myblockingSocket,responsedata);
}
What is the recommended way to make these calls accessible in .NET as asynchronous calls using async-await (without changing the original DLL) ?
I read: https://learn.microsoft.com/en-us/dotnet/standard/async-in-depth#deeper-dive-into-tasks-for-an-io-bound-operation and https://learn.microsoft.com/en-us/dotnet/csharp/async and several other pages and did not find another solution than spawning a new task, which is not recommended to do on I/O bound operations because of the task creation overhead.
What is the recommended way to make these calls accessible in .NET as asynchronous calls using async-await (without changing the original DLL) ?
There is no recommended solution because this isn't possible. Either the DLL itself must be changed/replaced so that it supports asynchrony, or the asynchronous calls will just be running the synchronous code on a background thread - what I call "fake asynchrony" because it appears asynchronous but is actually taking up a thread anyway.
... did not find another solution than spawning a new task, which is not recommended to do on I/O bound operations because of the task creation overhead.
It's actually not recommended for a couple of reasons:
It lies to the upstream code. It says "this API is asynchronous" when it's not. This can lead consumers to make incorrect decisions, e.g., preferring the asynchronous API in a server scenario.
It doesn't provide any actual benefit. Implementing a method with Task.Run forces the consumers to use an additional thread. If you just kept the API synchronous, then consumers can choose to call it with Task.Run or not, depending on their needs.
I've been reading about the new async and await operators in C# and tried to figure out in which circumstances they would possibly be useful to me. I studied several MSDN articles and here's what I read between the lines:
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
async void button1_Click(object sender, EventArgs e)
{
// even though this call takes a while, the UI thread will not block
// while it is executing, therefore allowing further event handlers to
// be invoked.
await SomeLengthyOperationAsync();
}
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
In other words, if you create a thread with an ordinary good old ThreadStart entry point (or a Console application with good old static int Main(string[] args)), then you cannot use async and await because at one point you would have to use await, and make the method that uses it async, and hence in the calling method you also have to use await and make that one async and so on. But once you reach the thread entry point (or Main()), there's no caller to which an await would yield control to.
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop. I guess all that makes indeed sense, since MSDN states that async programming does not mean multithreading, but using the UI thread's spare time instead; when using a console application or a thread with a user defined entry point, multithreading would be necessary to perform asynchronous operations (if not using a compatible message loop).
My question is, are these assumptions accurate?
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop.
That's absolutely not the case.
In Windows Forms and WPF, async/await has the handy property of coming back to the UI thread when the asynchronous operation you were awaiting has completed, but that doesn't mean that's the only purpose to it.
If an asynchronous method executes on a thread-pool thread - e.g. in a web service - then the continuation (the rest of the asynchronous method) will simply execute in any thread-pool thread, with the context (security etc) preserved appropriately. This is still really useful for keeping the number of threads down.
For example, suppose you have a high traffic web service which mostly proxies requests to other web services. It spends most of its time waiting for other things, whether that's due to network traffic or genuine time at another service (e.g. a datbase). You shouldn't need lots of threads for that - but with blocking calls, you naturally end up with a thread per request. With async/await, you'd end up with very few threads, because very few requests would actually need any work performed for them at any one point in time, even if there were a lot of requests "in flight".
The trouble is that async/await is most easily demonstrated with UI code, because everyone knows the pain of either using background threads properly or doing too much work in the UI thread. That doesn't mean it's the only place the feature is useful though - far from it.
Various server-side technologies (MVC and WCF for example) already have support for asynchronous methods, and I'd expect others to follow suit.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
Not true - methods marked async just mean they can use await, but callers of those methods have no restrictions. If the method returns Task or Task<T> then they can use ContinueWith or anything else you could do with tasks in 4.0
A good non-UI example is MVC4 AsyncController.
Ultimately, async/await is mostly about getting the compiler rewriting so you can write what looks like synchronous code and avoid all the callbacks like you had to do before async/await was added. It also helps with the SynchronizationContext handling, useful for scenarios with thread affinity (UI frameworks, ASP.NET), but even without those, it's still useful. Main can always do DoStuffAsync().Wait(); for instance. :)
My question is, are these assumptions accurate?
No.
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
True. Also true for other UI applications including Silverlight and Windows Store.
And also true for ASP.NET. In this case, it's the HTTP request thread that is not blocked.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
This is a best practice ("async all the way down"), but it's not strictly required. You can block on the result of an asynchronous operation; many people choose to do this in Console applications.
an ordinary good old ThreadStart entry point
Well... I do have to take issue with "ordinary good old". As I explain on my blog, Thread is pretty much the worst option you have for doing background operations.
I recommend you review my introduction to async and await, and follow up with the async / await FAQ.
async-await is only wrapper for Task class manipulations, which is part of so named Tasks Parallel Library - TPL(published before async-await auto code generation tech.)
So fact is you may not use any references to UI controls within async - await.
Typically async-await is powerfull tool for any web and server relations, loading resources, sql. It works with smart waiting data with alive UI.
Typically TPL application: from simple big size loop till multi stages parallel calculations in complex calculations based on shared data (ContinueWith and so on)
I have a repository with a method Insert that returns an int (the methods and types are not relevant here). I am thinking to create synchronous and asynchronous insert methods for this repository. For the asynchronous method is it a good practice to enclose the synchronous Insert method in a task to avoid the code duplication?
No, this is not a good practice, as detailed by Microsoft's Stephen Toub here:
https://blogs.msdn.microsoft.com/pfxteam/2012/03/24/should-i-expose-asynchronous-wrappers-for-synchronous-methods/
... and by Stephen Cleary here:
http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html
Long story short, if all your method does is wrap a synchronous call in Task.Run, that's trivial and I'm sure the caller is perfectly capable of doing it themselves. There is no need to increase the surface area of your API unless you have a naturally asynchronous operation (or unless you know that in the future you'll be able to provide one, and therefore want the consumers to target the XxxAsync method from day one).
As a bonus, here's a real life example of async wrapper methods being removed from a popular library:
JSON.NET used to provide SerializeAsync and DeserializeAsync methods which were just wrappers around their synchronous counterparts using Task.Factory.StartNew. Those were eventually obsoleted as they don't add value to the API and were deemed a potential scalability issue. The full discussion which led to this change can be found here:
https://github.com/JamesNK/Newtonsoft.Json/issues/66
I've been reading about the new async and await operators in C# and tried to figure out in which circumstances they would possibly be useful to me. I studied several MSDN articles and here's what I read between the lines:
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
async void button1_Click(object sender, EventArgs e)
{
// even though this call takes a while, the UI thread will not block
// while it is executing, therefore allowing further event handlers to
// be invoked.
await SomeLengthyOperationAsync();
}
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
In other words, if you create a thread with an ordinary good old ThreadStart entry point (or a Console application with good old static int Main(string[] args)), then you cannot use async and await because at one point you would have to use await, and make the method that uses it async, and hence in the calling method you also have to use await and make that one async and so on. But once you reach the thread entry point (or Main()), there's no caller to which an await would yield control to.
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop. I guess all that makes indeed sense, since MSDN states that async programming does not mean multithreading, but using the UI thread's spare time instead; when using a console application or a thread with a user defined entry point, multithreading would be necessary to perform asynchronous operations (if not using a compatible message loop).
My question is, are these assumptions accurate?
So basically you cannot use async and await without having a GUI that uses the standard WinForms and WPF message loop.
That's absolutely not the case.
In Windows Forms and WPF, async/await has the handy property of coming back to the UI thread when the asynchronous operation you were awaiting has completed, but that doesn't mean that's the only purpose to it.
If an asynchronous method executes on a thread-pool thread - e.g. in a web service - then the continuation (the rest of the asynchronous method) will simply execute in any thread-pool thread, with the context (security etc) preserved appropriately. This is still really useful for keeping the number of threads down.
For example, suppose you have a high traffic web service which mostly proxies requests to other web services. It spends most of its time waiting for other things, whether that's due to network traffic or genuine time at another service (e.g. a datbase). You shouldn't need lots of threads for that - but with blocking calls, you naturally end up with a thread per request. With async/await, you'd end up with very few threads, because very few requests would actually need any work performed for them at any one point in time, even if there were a lot of requests "in flight".
The trouble is that async/await is most easily demonstrated with UI code, because everyone knows the pain of either using background threads properly or doing too much work in the UI thread. That doesn't mean it's the only place the feature is useful though - far from it.
Various server-side technologies (MVC and WCF for example) already have support for asynchronous methods, and I'd expect others to follow suit.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
Not true - methods marked async just mean they can use await, but callers of those methods have no restrictions. If the method returns Task or Task<T> then they can use ContinueWith or anything else you could do with tasks in 4.0
A good non-UI example is MVC4 AsyncController.
Ultimately, async/await is mostly about getting the compiler rewriting so you can write what looks like synchronous code and avoid all the callbacks like you had to do before async/await was added. It also helps with the SynchronizationContext handling, useful for scenarios with thread affinity (UI frameworks, ASP.NET), but even without those, it's still useful. Main can always do DoStuffAsync().Wait(); for instance. :)
My question is, are these assumptions accurate?
No.
You can use async for Windows Forms and WPF event handlers, so they can perform lengthy tasks without blocking the UI thread while the bulk of the operation is being executed.
True. Also true for other UI applications including Silverlight and Windows Store.
And also true for ASP.NET. In this case, it's the HTTP request thread that is not blocked.
A method using await must be async, which means that the usage of any async function somewhere in your code ultimately forces all methods in the calling sequence from the UI event handlers up until the lowest-level async method to be async as well.
This is a best practice ("async all the way down"), but it's not strictly required. You can block on the result of an asynchronous operation; many people choose to do this in Console applications.
an ordinary good old ThreadStart entry point
Well... I do have to take issue with "ordinary good old". As I explain on my blog, Thread is pretty much the worst option you have for doing background operations.
I recommend you review my introduction to async and await, and follow up with the async / await FAQ.
async-await is only wrapper for Task class manipulations, which is part of so named Tasks Parallel Library - TPL(published before async-await auto code generation tech.)
So fact is you may not use any references to UI controls within async - await.
Typically async-await is powerfull tool for any web and server relations, loading resources, sql. It works with smart waiting data with alive UI.
Typically TPL application: from simple big size loop till multi stages parallel calculations in complex calculations based on shared data (ContinueWith and so on)
I am quite new to Metro dev and I only hope I will be able to express my question in an understandable way...
Actually I am porting a part of my old application to Metro. The logic part is a separated project (Portable Library) and it should serve to 1) the old WPF app and 2) the new Metro app. The basic logic is the same but some subsystems (for example file operations manager) must be coded differently - i.e. async way for Metro.
My question is: Do I have to rewrite the whole chain of methods caller-callee to the new async paradigm? Let's say I have a chain of 4 methods, starting by method A = Metro UI event async handler (it makes sense to me to code it as async void as it is the top fire&forget event), through the next 2 methods (B and C) placed in different layers of my application, down to the method D containing "await CreateFileAsync" method (made async by Microsoft).
Now: async CreateFileAsync method should be called with await. That forces me to make method D async too. To call method D from C and C from B and B from A - do I have to rewrite all A, B and C into the async-await style?
I can feel I am missing a deeper knowledge so I am trying to educate myself but concurrently I wanted to try my luck here...
Do I have to rewrite a big part of my code? Is any of my statements above wrong?
Many thanks in advance, Hans
I recommend that you do rewrite your portable library to be asynchronous. It's not as bad as it used to be; Microsoft worked very hard on async/await to make it as easy as possible to convert synchronous code to asynchronous. I expect that a whole lot of others will be doing the same in the near future, and R# will probably implement a "make async" rewriting.
There are non-obvious pitfalls when mixing synchronous and asynchronous code - see Stephen Toub's last blog post Should I expose synchronous wrappers for asynchronous methods? For this reason, I think it's just cleaner to expose asynchronous operations as asynchronous APIs (and synchronous operations as synchronous APIs).
Update: If you do want synchronous code to call asynchronous code, then you can use the Task.WaitAndUnwrapException extension method in my AsyncEx library. However, you still have the problems mentioned in Stephen Toub's post, namely these:
You can deadlock if your library doesn't use ConfigureAwait(false) everywhere it can.
You can also deadlock if you run into the maximum number of threads in the thread pool.
(2) is not that common anymore, but (1) is a real possibility. It's regularly brought up by people who are just testing out async so they mix it with synchronous code.