Dom*_*nas 0 c# wpf multithreading dispatcher observablecollection
通常我会检查我是否可以访问ObservableCollection,如果没有,我会调用一个Dispatcher. 这里(上Stackoverflow)还有其他一些解决方案,但我不知道什么是最好和最干净的方法。我认为我的解决方案已经过时,不应再使用。
在我的例子中是ItemsCollection绑定到UI. 该_UpdateTheCollectionFromAnotherThread()会被调用(从另一个thread或将开启另一个thread)并保存数据暂时到items。之后,我会检查访问权限并dispatcher在需要时调用 a 。
这是我必须走的路还是有一些更好更清洁的解决方案?
public class FooClass
{
// ##############################################################################################################################
// Properties
// ##############################################################################################################################
/// <summary>
/// This Items are bound to my UI.
/// </summary>
public ObservableCollection<string> ItemsCollection { get; } = new ObservableCollection<string>();
// ##############################################################################################################################
// Singleton pattern
// ##############################################################################################################################
/// <summary>
/// The instance of <see cref="FooClass"/>.
/// </summary>
internal static FooClass Instance => _Instance ?? (_Instance = new FooClass());
private static FooClass _Instance;
// ##############################################################################################################################
// Konstruktor
// ##############################################################################################################################
private FooClass()
{
}
// ##############################################################################################################################
// Method
// ##############################################################################################################################
private void _UpdateTheCollectionFromAnotherThread()
{
List<string> items = new List<string>();
//Here would be some logic to create and fill the items list....
//and now apply them to the public list
if (System.Windows.Application.Current.Dispatcher.CheckAccess())
{
ItemsCollection.Clear();
foreach (string item in items)
{
ItemsCollection.Add(item);
}
}
else
{
System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
ItemsCollection.Clear();
foreach (string item in items)
{
ItemsCollection.Add(item);
}
}));
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您使用的是 .NET Framework 4.5 或更高版本,则可以通过调用该BindingOperations.EnableCollectionSynchronization方法启用跨多个线程访问集合。请注意,必须在 UI 线程上调用此方法:
public class FooClass
{
private readonly object _lock = new object();
public ObservableCollection<string> ItemsCollection { get; } = new ObservableCollection<string>();
internal static FooClass Instance => _Instance ?? (_Instance = new FooClass());
private static FooClass _Instance;
private FooClass()
{
BindingOperations.EnableCollectionSynchronization(ItemsCollection, _lock);
}
private void _UpdateTheCollectionFromAnotherThread()
{
List<string> items = new List<string>();
ItemsCollection.Clear();
foreach (string item in items)
{
ItemsCollection.Add(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果FooClass可能是在后台线程上创建的,您仍然可以通过不重复自己来改进代码:
public class FooClass
{
public ObservableCollection<string> ItemsCollection { get; } = new ObservableCollection<string>();
internal static FooClass Instance => _Instance ?? (_Instance = new FooClass());
private static FooClass _Instance;
private FooClass() { }
private void _UpdateTheCollectionFromAnotherThread()
{
List<string> items = new List<string>();
if (System.Windows.Application.Current.Dispatcher.CheckAccess())
ClearCollection(items);
else
System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => ClearCollection(items)));
}
private void ClearCollection(List<string> items)
{
ItemsCollection.Clear();
foreach (string item in items)
{
ItemsCollection.Add(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2163 次 |
| 最近记录: |