2016-04-12 19 views
2

我有一個WPF應用程序更新其數據模型內更新其數據在1赫茲的計時器。據我瞭解,一個計時器在GUI上的一個單獨的線程上工作。一切似乎都很好,但我正在閱讀並查看是否可以在與GUI線程不同的線程上更新數據時出現衝突的報告。我們使用.NET框架4客戶端配置文件運行。下面的文章說事情是固定在4.5,但它仍然不清楚,它是。有人能爲我澄清這一點嗎?到目前爲止,我們還沒有在綁定中使用集合。這就是爲什麼我們沒有麻煩。將WPF控件綁定到Timer中更新的數據是否安全?

WPF Databinding thread safety?

+0

使用DispatcherTimer。它的Tick事件在UI線程中引發。 – Clemens

回答

2

是的。它是線程安全的。 INotifyPropertyChanged總是從其他線程封送到UI線程。

由於PropertyChanged事件被自動封送到UI調度程序,所以不需要從另一個線程調度PropertyChanged到UI線程。

由於a MSDN article說:

注意,在WPF中,事情是不同的,在圖5所示 代碼工作即使狀態屬性數據綁定到一個TextBlock。這個 是因爲WPF自動調度PropertyChanged事件到 主線程,不像所有其他XAML框架。在所有其他 框架中,需要調度解決方案。

然而,這是僅適用於標量屬性(即PropertyChanged事件)更改通知真。收集更改通知(INotifyCollectionChanged.CollectionChanged事件)不以這種方式工作,它們必須手動在UI線程上引發。也就是說,在使用INotifyCollectionChanged(例如ObservableCollection)時,這些更改不會封送到UI線程。這意味着如果您從非UI線程修改集合,則會發生異常。例如,有一些ViewModel我們在ViewModel類中,我們不使用分派器來更新UI。所以,我建議你使用大衛·裏卡德的做法:

public static class DispatchService 
{ 
    public static void Invoke(Action action) 
    { 
     Dispatcher dispatchObject = Application.Current.Dispatcher; 
     if (dispatchObject == null || dispatchObject.CheckAccess()) 
    { 
      action(); 
     } 
     else 
     { 
      dispatchObject.Invoke(action); 
     } 
    } 
} 

和:

DispatchService.Invoke(() => 
{ 
    this.MyCollection.Add("new value"); 
}); 

David Rickard article at msdn blog.

更新:

呀,article使用MVVMLight框架。但是,MVVM Light使用Dispatcher將標量屬性編組爲UI線程是不正確的。可以從ViewModelBase類的源代碼MVVM Light看出there is no marshal between threads to update scalar property。請參閱RaisePropertuChanged()方法。

爲了打消調度標性質的任何疑問,我做了一個試驗:

XAML:

<TextBlock Text="{Binding Number}" FontSize="188" Foreground="Red" /> 

視圖模型:

public int Number { get; set; } 

private void UpdateNumber() 
{ 
     Task.Run(() => 
     { 
      System.Timers.Timer timer = new System.Timers.Timer(250); 
      timer.Elapsed += (sender, eventArgs) => 
      { 
       Number++; 
       OnPropertyChanged("Number");//No exceptions, no errors 
      }; 
      timer.Enabled = true; 
     }); 
} 

更新1:

毫無疑問,INotifyProperyChanged事件由WPF自動發送給UI主題。我相信a MSDN article和你在問題中顯示的link :)。

請注意:這是因爲WPF自動將PropertyChanged事件分派到主線程,與所有其他XAML框架不同。

+0

請注意,本文正在使用切換到UI線程的MVVM Light框架。所以這個答案對所有的WPF應用程序來說都是不正確的。 –

+1

非常有趣。謝謝。 –

+0

@ErnodeWeerd,你能澄清一下WPF不起作用嗎?我們沒有使用MVVM Light框架。 – bsh152s

1

不,它不是線程安全的。解決這個問題的常見方法是切換到notify屬性更改事件的提升者中的UI線程。

更新視圖或視圖模型每秒1000次通常是無用的,因爲顯示僅每秒更新60次左右,而普通用戶無法在文本中每秒讀取一千個值。

引發通知事件的相同代碼可能會限制事件每秒產生的次數。