使用async和await

时间:2014-03-29 12:30:21

标签: c# multithreading asynchronous task-parallel-library

    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));
    }

我想让两个方法(1.domaminModel.Load(),2。UpdateState())一个接一个地在同一个线程上运行。不在UI线程上。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

请考虑以下代码:

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

DoOne 不会在 UI线程(!)中执行,其线程将成为方法的调用者的线程 Sample() 名为 来电者主题

在大多数情况下,在客户端,调用者线程是UI线程,因为大多数代码都是由用户操作(例如鼠标单击)调用的,但它不是固定的行为。

DoTwo 将在一个单独的线程中执行,很明显它不会在调用者线程中执行。

DoThree 将在来电者主题中执行

DoFour 将在UI线程中执行,无论是什么是调用者线程都无关紧要。

所以@usr的评论是完全错误的。

要实现目标,请按以下方式更改代码:

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));
    }

答案 1 :(得分:1)

  

我想制作两种方法(1.domaminModel.Load(),2。   UpdateState())一个接一个地在同一个线程上运行。不开   UI线程。

已更新,如果您只想在单独的非UI线程上运行_domainModel.LoadImageSelectionViewModel.UpdateState,请执行以下操作:

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);
}

请注意,您需要DispatcherHelper.UIDispatcher.Invoke()包装。

<小时/> 如果您希望InitData之后的_domainModel.Load的其余部分在单独的主题上运行:

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)
    });
}

请注意,Task.Run将自动解包您的嵌套任务(Task<Task<T>>)。此外,您可能需要在ProgressIndicatorViewModel.Stop()内移动Dispatcher.Invoke

根据_domainModel.Load内的内容,您甚至可能不需要Task.Run

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

请注意,您应该在async void InitData方法中处理异常。你无法在它之外处理它们。