簡體   English   中英

WPF MVVMLight Messenger UI線程問題

[英]WPF MVVMLight Messenger UI thread issue

我在WPF(MVVM)應用程序中使用MVVMLight Messenger時遇到問題。 在視圖中,我具有一個元素( LoadingControl ),該元素的可見性屬性通過使用自定義可見性轉換器綁定到viewmodel屬性( IsBusy )。 在視圖模型中,我通過發送MVVM消息來更改屬性值( IsBusy ):

Messenger.Default.Send(new LoadingMessage(true));

在這里,我有一個視圖模型中的方法,該方法重新設計為接受LoadingMessage消息,其中IsBusy屬性已更改。

這很好用,但是在我發送此消息的viewmodel方法之一中,UI線程塊和IsBusy屬性值發生了變化,但是直到主要操作未完成時,UI元素LoadingControl的可見性才出現,例如:

void Call() {
    Messenger.Default.Send(new LoadingMessage(true));

    SomeServiceCall();
    Navigate(); // <- this works with UI, too
} // <- this is the place when LoadingControl is shown.

我猜問題是因為在視圖模型中執行不在ui線程上,所以我嘗試直接在Call()方法中調用此方法:

DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
    IsBusy = true;
});

但這也行不通,直到方法結束才顯示LoadingControl 由於我不太熟悉多線程,因此我認為這里還有其他問題。 任何幫助表示贊賞。

Messenger在您的線程中發送消息,因此您需要等待。 我認為您需要在另一個線程中發送消息。

DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
    Messenger.Default.Send(new LoadingMessage(true));
});

另一種(更輕松的)方法是使用Task觸發並忘記代碼

Task.Factory.StartNew(() => 
   { 
       Messenger.Default.Send(new LoadingMessage(true));
       SomeServiceCall();
       Navigate();
   });

如果要強制在另一個線程上執行Action ,則可以將TaskScheduler.Default傳遞給StartNew()調用。 但是這樣做可能會導致Invalid cross-thread access Exception ,因為您的代碼不再在UI線程上執行,而是在Background線程上執行。 因此,您可能需要使用Dispatcher將代碼設置視圖范圍的屬性(例如IsBusyDispatcher回UI-Thread:

Application.Current.Dispatcher.BeginInvoke(() =>
{
    IsBusy = true;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM