gpt4 book ai didi

wpf - 为什么我应该避免使用 Dispatcher?

转载 作者:行者123 更新时间:2023-12-04 12:24:43 25 4
gpt4 key购买 nike

我已经阅读了许多关于绑定(bind)和 GUI 控件的线程亲和性的帖子、文章等。有些帖子人们不想使用Dispatcher .

我还有一个同事避免在他的代码中使用 Dispatcher。我问他原因,但他的回答并不让我满意。他说,他不喜欢这种隐藏在类里面的“魔法”。

好吧,我是以下类(class)的粉丝。


public class BindingBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

private Dispatcher Dispatcher
{
#if SILVERLIGHT
get { return Deployment.Current.Dispatcher; }
#else
get { return Application.Current.Dispatcher; }
#endif
}

protected void RaisePropertyChanged<T>(Expression<Func<T>> expr)
{
var memberExpr = (MemberExpression)expr.Body;
string property = memberExpr.Member.Name;

var propertyChanged = PropertyChanged;
if (propertyChanged == null) return;

if (Dispatcher.CheckAccess())
propertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
else
Dispatcher.BeginInvoke(() => RaisePropertyChanged(expr));
}
}

这是问题。有些人不想使用这样的类(class)有什么原因吗?也许我必须重新考虑这种方法。

你必须承认,有一件奇怪的事情。 Dispatcher.CheckAccess()被排除在 Intellisense 之外。也许由于这个事实,他们有点害怕。

问候

编辑:

好的,另一个例子。考虑一个复杂的对象。作为示例的集合可能不是最好的主意。

public class ExampleVm : BindingBase
{
private BigFatObject _someData;
public BigFatObject SomeData
{
get { return _someData; }
set
{
_someData = value;
RaisePropertyChanged(() => SomeData);
}
}

public ExampleVm()
{
new Action(LoadSomeData).BeginInvoke(null, null); //I know - it's quick and dirty
}

private void LoadSomeData()
{
// loading some data from somewhere ...
// result is of type BigFatObject

SomeData = result; // This would not work without the Dispatcher, would it?
}
}

最佳答案

我个人也不反对Dispatcher在 View 模型类中。我没有看到任何重大问题,但它为您的代码提供了最大的灵 active 。

但我喜欢封装 Dispatcher 的用法的想法。尽可能在基础设施代码中。就像你对 RaisePropertyChanged 所做的那样方法(顺便说一句,在 RaisePropertyChanged 的情况下,您不必发送任何东西 - 绑定(bind)已经为您完成;您只需发送对集合的更改)。

我在这里看到的最大和唯一的缺点是单元测试。当您尝试测试涉及使用 Dispatcher 的逻辑时,事情会变得棘手。 .想象一下,如果你在 View 模型中有这样的代码:

private void UpdateMyCollection() 
{
IList<ModelData> dataItems = DataService.GetItems();

// Update data on UI
Dispatcher.BeginInvoke(new Action(() => {
foreach (ModelData dataItem in dataItems)
{
MyObservableCollection.Add(new DataItemViewModel(dataItem));
}
}));
}

这种代码在从非 UI 线程更新集合时非常典型。现在,您将如何编写一个单元测试来测试将项目添加到可观察集合的逻辑?首先,您需要模拟 Dispatcher属性,因为 Application.Currentnull在单元测试执行期间。其次,你将如何 mock 它?你会创建一个特殊的线程来模仿 UI 线程并使用 Dispatcher那个线程?所以,这种事情。

底线是,如果您希望您的代码对单元测试友好,您需要考虑如何模拟 Dispatcher。 .这是唯一的担忧。

更新:

您提供的第二个示例将在没有 Dispatcher 的情况下工作。 (绑定(bind)就可以了)。

关于wpf - 为什么我应该避免使用 Dispatcher?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5217491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com