Reputation: 853
I have such question. For example I create dynamically custom userControl using mvvm pattern. So I've sended a command to create an userControl. So creation looks like
private async Task<bool> OnAddUserControl1(List<ALV_VM_ADWERT> control)
{
try
{
_cancellationTokenSource = new CancellationTokenSource();
var userControl = _userControlsContainer.CreateUserControl1(control);
var task1 = Task.Factory.StartNew(() =>
{
userControl.ViewModel.InOperationEvent += OnUsercontrolInOperationChanged;
userControl.ViewModel.ValueTypeChangedEvent += OnValueTypeChanged;
userControl.ViewModel.SetExpandableName += OnSetExpandableName;
}, _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
var task2 = Task.Factory.StartNew(() => FinalCreatingStep(userControl, control[0].RAUMNAME.Trim()), _cancellationTokenSource.Token, TaskCreationOptions.AttachedToParent, TaskScheduler.FromCurrentSynchronizationContext());
await Task.WhenAll(task1, task2);
return true;
}
catch (Exception)
{
return false;
}
}
and my question is - does it make sence to create child tasks, or it is better to have code without child tasks? And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?
Upvotes: 2
Views: 5478
Reputation: 456487
Your current code doesn't make any sense.
The point of async
code in a UI application is responsiveness - i.e., moving long-running operations off the UI thread. As @Gusdor pointed out, most of the use cases for async
are I/O-based (or event-based) operations, where you don't want to block the UI thread just to wait for some result. Another use case is when you have some CPU-bound work to do, but you don't want to tie up the UI thread; in this case, you can use Task.Run
.
But in your code, you're calling StartNew
with TaskScheduler.FromCurrentSynchronizationContext
, which means your "child" tasks are going to execute on the UI thread. So your OnAddUserControl1
is just starting tasks which will run on the same thread and asynchronously waiting for them to complete. This is a very complex way of doing nothing.
While we're on the subject of StartNew
, there are a number of other problems:
CancellationToken
without ever observing it in the delegate.AttachedToParent
which is incorrect for await
-compatible tasks.TaskScheduler
which will run the delegate right back on the UI thread.If you need to use background (thread pool) tasks, you should use Task.Run
instead of Task.Factory.StartNew
; I go into more detail on my blog.
So for this example, it doesn't make sense to use async
or await
at all.
The best way to start using async
is to identify the I/O-bound (or event-driven) parts first (e.g., HTTP requests, database calls), make them async
, and then work your way up the call stack.
Upvotes: 2
Reputation: 14334
Do those event subscriptions really need to be asynchronous? You may be trying too hard to use asynchronous code.
The user control constructor is usually the most time consuming part and must be done on the UI thread. Asynchronous operations are generally only required when some form of IO or processing is involed;
In short, an asynchronous task is probably overkill here.
Upvotes: 4
Reputation: 17003
Does it make sence to create child tasks, or it is better to have code without child tasks?
It is depending on your requirements. If your UI will blocked (Freeze) for long time you have to create a child task, otherwise not!
And if the answer is yes, then should I make all methods async? If not, what methods I should not make async?
Here it is also depending on your requirements and your .Net Version. If you are using .NET 4.5 the easiest way to do that with Async await. If you are using .Net 3.5 than just use Task. If .Net 2 use BackgorundWorker else use Thread class. ONLY Asynchrony methods must get the word async. Other methods you do not have to change them. In other words only the method which blocked the UI.
Upvotes: 3