Dil*_*hod 9 c# collections wpf multithreading observablecollection
我有两个WPF应用程序"UI","调试器"和一个ClassLibrary"BL".UI对Debugger和BL的引用.调试器引用BL.我在BL中收集了名为MyCollection的集合.UI应用程序启动调试器应用程序,调试器绑定到BL中的集合MyCollection.当我尝试从UI应用程序更改MyCollection集合时,我遇到异常.
A first chance exception of type 'System.NotSupportedException' occurred in PresentationFramework.dll
Additional information: This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.
Run Code Online (Sandbox Code Playgroud)
我在google搜索并发现:BindingOperations.EnableCollectionSynchronization 我无法弄清楚如何使用它.我不想引用我的BL项目中的任何UI dll.任何人都可以帮助我吗?
谢谢您的帮助!
Dre*_*kes 25
我在Stack Overflow上看到的所有示例都是错误的.你必须从另一个线程修改时,它锁定集合.
在调度程序(UI)线程上:
_itemsLock = new object();
Items = new ObservableCollection<Item>();
BindingOperations.EnableCollectionSynchronization(Items, _itemsLock);
Run Code Online (Sandbox Code Playgroud)
然后从另一个线程:
lock (_itemsLock)
{
// Once locked, you can manipulate the collection safely from another thread
Items.Add(new Item());
Items.RemoveAt(0);
}
Run Code Online (Sandbox Code Playgroud)
本文中的更多信息:http:/ 10/ 10rem.net/blog/2012/01/20/wpf-45-cross-thread-collection-synchronization-redux
我不确定这是否会有所帮助,但你仍然可以尝试一下.
添加Property在Debugger其将持有Collection的BL像
private ObservableCollection<string> _data = new ObservableCollection<string>();
private object _lock = new object();
public ObservableCollection<string> Data { get {return _data;} }
Run Code Online (Sandbox Code Playgroud)
在构造函数中只需添加以下行
BindingOperations.EnableCollectionSynchronization(_data, _lock);
Run Code Online (Sandbox Code Playgroud)
这将上面的线将照顾线程安全.
以下是示例
ViewModel(Debugger)
internal class ViewModelClass : INotifyPropertyChanged
{
private object _lock = new object ();
private ObservableCollection<string> _data;
public ObservableCollection<string> Data
{
get { return _data; }
private set
{
_data = value;
RaisePropertyChanged ("Data");
}
}
private string _enteredText;
public string EnteredText
{
get { return _enteredText; }
set
{
_enteredText = value;
_data.Add (value); RaisePropertyChanged ("EnteredText");
}
}
private void RaisePropertyChanged (string name)
{
var pc = PropertyChanged;
if (pc != null)
pc (this, new PropertyChangedEventArgs (name));
}
public ViewModelClass ()
{
var _model = new ModelClass ();
Data = _model.Data;
_data.CollectionChanged += (s, e) => RaisePropertyChanged ("Data");
}
public event PropertyChangedEventHandler PropertyChanged;
}
Run Code Online (Sandbox Code Playgroud)
型号(BL)
internal class ModelClass
{
private ObservableCollection<string> _data;
public ObservableCollection<string> Data
{
get { return _data; }
private set { _data = value; }
}
public ModelClass ()
{
_data = new ObservableCollection<string> { "Test1", "Test2", "Test3" };
}
}
Run Code Online (Sandbox Code Playgroud)
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow ()
{
InitializeComponent ();
this.DataContext = new ViewModelClass ();
}
}
Run Code Online (Sandbox Code Playgroud)
MainWindow.xaml
<Window x:Class="CollectionSynchronizationTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<StackPanel>
<ComboBox IsEditable="True"
ItemsSource="{Binding Data}"
Text="{Binding EnteredText, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
<Button Content="Test" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
当窗口加载时只需输入"SomeValue" ComboBox然后在按下Tab键后你应该在ComboBox下拉列表中找到新值
| 归档时间: |
|
| 查看次数: |
19889 次 |
| 最近记录: |