Question

    public async override void InitData()
    {
        _domainModel = new DomainModel()

        ProgressIndicatorViewModel.Start();
        _State = Getstate();
        await _domainModel.Load(_State, ProgressIndicatorViewModel); //returns a task
        ImageSelectionViewModel.UpdateState(_State); //returns void not a task!
        ProgressIndicatorViewModel.Stop();

        DispatcherHelper.UIDispatcher.Invoke(() => ImageSelectionViewModel.RefreshImages(_imageList));
    }

i would like to make the two methods (1.domaminModel.Load(), 2. UpdateState()) to run on the same thread one after the other. not on the UI thread.

how can i do this?

Was it helpful?

Solution

i would like to make the two methods (1.domaminModel.Load(), 2. UpdateState()) to run on the same thread one after the other. not on the UI thread.

Updated, if you want only _domainModel.Load and ImageSelectionViewModel.UpdateState to run on a separate non-UI thread, then just do this:

public async override void InitData()
{
    _domainModel = new DomainModel()

    ProgressIndicatorViewModel.Start();
    _State = Getstate();
    await Task.Run(async () =>
    { 
        await _domainModel.Load(_State, ProgressIndicatorViewModel))
        ImageSelectionViewModel.UpdateState(_State); //returns void not a task!
    });
    ProgressIndicatorViewModel.Stop();

    ImageSelectionViewModel.RefreshImages(_imageList);
}

Note you do not need DispatcherHelper.UIDispatcher.Invoke() wrapper then.


If you want the rest of InitData after _domainModel.Load to run on a separate thread:

public async override void InitData()
{
    _domainModel = new DomainModel()

    ProgressIndicatorViewModel.Start();
    _State = Getstate();
    await Task.Run(() => _domainModel.Load(_State, 
        ProgressIndicatorViewModel)).ConfigureAwait(false);
    ImageSelectionViewModel.UpdateState(_State); //returns void not a task!

    DispatcherHelper.UIDispatcher.Invoke(() =>
    {
        ProgressIndicatorViewModel.Stop();
        ImageSelectionViewModel.RefreshImages(_imageList)
    });
}

Note that Task.Run will automatically unwrap the nested task (of Task<Task<T>>) for your here. Also, you'd probably need to move ProgressIndicatorViewModel.Stop() inside Dispatcher.Invoke.

Depending on what's inside _domainModel.Load, you may not even need Task.Run:

await _domainModel.Load(_State, 
    ProgressIndicatorViewModel).ConfigureAwait(false);

One a side note, you should probably handle exceptions inside your async void InitData method. You won't be able to handle them outside it.

OTHER TIPS

Consider following codes:

public async void Sample()
{
     DoOne();
     await DoTwo();
     DoThree();
     Dispather.BeginInvoke(() => DoFour());
}

DoOne Will not executed in UI Thread (!), its thread will be a thread that is a caller of method Sample() named Caller Thread

In most cases in client side the Caller thread is UI Thread, because most codes are invoked by user actions (such as mouse click), but it's not a fixed behavior.

DoTwo will be executed in a separated thread, it's clear that it will not be executed in caller thread.

DoThree will be executed in a Caller Thread

and DoFour will be executed at UI Thread, it does not matter that what's a caller thread.

So the comment of @usr is totally wrong.

To achieve your goal change your code as following:

public async override void InitData()
    {
        _domainModel = new DomainModel()

        ProgressIndicatorViewModel.Start();
        _State = Getstate();
        await Task.Factory.StartNew(() => {
             _domainModel.Load(_State, ProgressIndicatorViewModel).ContinueWith(() => {
             ImageSelectionViewModel.UpdateState(_State); }); 
           };
        ProgressIndicatorViewModel.Stop();

        DispatcherHelper.UIDispatcher.Invoke(() => ImageSelectionViewModel.RefreshImages(_imageList));
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top