通常情况下,我会检查是否可以访问ObservableCollection
,如果没有,我会调用Dispatcher
。这里(Stackoverflow
)也是其他一些解决方案,但我不知道什么是最好和最干净的方法。我认为我的解决方案已经过时,不应再使用了。
在我的示例中,ItemsCollection
绑定到UI
。 _UpdateTheCollectionFromAnotherThread()
将被调用(来自另一个thread
或将打开另一个thread
)并将数据临时保存到items
。之后,我会检查访问权限并在需要时拨打dispatcher
。
这是我必须去的方式还是有更好更清洁的解决方案?
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);
}
}));
}
}
}
答案 0 :(得分:4)
如果您使用的是.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);
}
}
}
如果可以在后台线程上创建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);
}
}
}
答案 1 :(得分:0)
我无法判断您是否在此处实施MVC或MVW模式,但即使使用桌面应用,这也是一种很好的做法。
因此我认为ObservableCollection是视图的一部分,而不是模型,因为它通常不是功能模型所必需的,而是用于WPF UI绑定。 我说这个的主要原因是它是可变的&amp;它与WPF交互的整个方式依赖于可变性。
我没有_UpdateTheCollectionFromAnotherThread,因为你应该避免从另一个线程更新UI。 这样做通常意味着您的设计中存在模型 - 视图 - 控制器角色的混合。
相反,在模型中执行所有异步/多线程内容,因为这是处理大量处理的地方。
然后,在UI线程中使用模型更新UI更简单。