Sasha
Sasha

Reputation: 853

async /await for methods in wpf aplication

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

Answers (3)

Stephen Cleary
Stephen Cleary

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:

  1. The code is passing a CancellationToken without ever observing it in the delegate.
  2. The code is specifying AttachedToParent which is incorrect for await-compatible tasks.
  3. As mentioned above, the code is passing a 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

Gusdor
Gusdor

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;

  • Reading Files
  • Writing Files
  • Processing large data sets
  • Crossing the process boundary to talk to a server or connect device

In short, an asynchronous task is probably overkill here.

Upvotes: 4

Bassam Alugili
Bassam Alugili

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

Related Questions