2014-03-29 235 views
2
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线程上。使用异步和等待

我该怎么做?

+0

不是问题的关键,但'DispatcherHelper.UIDispatcher.Invoke'没有必要,因为您已经在UI线程上了。我很惊讶,即使运行。 – usr

+0

需要刷新可观察集合。别担心。运行完全 – Gilad

+0

'UpdateState'也是'async void',与'InitData'相同?有什么理由不使用'async Task'吗? – Noseratio

回答

1

我想使这两种方法(1.domaminModel.Load(),2 UpdateState())上运行一个接一个的相同的线程。不在 的UI线程上。

更新,如果你想只_domainModel.LoadImageSelectionViewModel.UpdateState到一个单独的非UI线程中运行,那么就这样做:

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方法内部异常。你将无法在它之外处理它们。

+1

我认为你的答案是错误的,因为你正在同一个线程[_domainModel.Load]&[ImageSelectionViewModel.UpdateState]&[ProgressIndicatorViewModel.Stop]中执行以下行,但他希望有[_domainModel.Load]&[ImageSelectionViewModel。例如,如果一个UI线程是一个调用者线程,而ProgressIndicatorViewModel.Stop()更改一个UI,那么你的代码将不会被执行 –

+1

@YasserMoradi,你可能是对的,虽然我不明白为什么@Gilad需要'DispatcherHelper.UIDispatcher.Invoke'那么我想他想在非UI线程上运行剩余的方法。答解决这两种情况。 – Noseratio

+0

'请注意,Task.Run会自动解开嵌套任务(任务>)在这里。“这是什么意思? –

1

考虑以下代码:(!)

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

DoOne不会UI线程,它的线程将是一个线程是方法样品的呼叫者()执行取名为来电线程

在客户端的大多数情况下,调用者线程是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)); 
    } 
+0

要使其按照您的预期工作,您需要对Task.Factory.StartNew的结果调用'Unwrap'。这是因为'ContinueWith'返回'Task',所以'Task.Factory.StartNew'将返回'Task ',并且不等待当前版本中的内部任务。 – Noseratio

+0

@Noseratio感谢您的回复,请注意,我的答案是概念性的,它甚至不会构建! ( - : –

+1

从概念上讲,我认为你需要在这里等待await或单个await和unwrap,否则在await后面的代码可能会在另一个线程上的UpdateState结束之前继续下去 – Noseratio