为什么multithreading访问WPF UI控件的开销?

在开发multithreading应用程序时需要编写大量重复代码时,我是否遗漏了WPF(以及之前的Windows窗体)。 应用程序中的每个UI控件最终都需要额外的代码行来获取和设置每个属性。

internal delegate void SetElementIsEnabledDelegate(UIElement element, bool isEnabled); internal delegate void SetBrushesAndTextDelegate(Brush foregroundBrush, string message); internal delegate void SetCheckBoxCheckedDelegate(CheckBox checkbox, bool checkedValue); internal delegate void SetTextBoxTextDelegate(TextBox richTextBox, string text); internal delegate void SetRichTextBoxTextDelegate(RichTextBox textBox, string text); internal static void SetElementIsEnabled(UIElement element, bool isEnabled) { if (element.Dispatcher.Thread != Thread.CurrentThread) { // Execute the same method, but this time on the GUI thread element.Dispatcher.Invoke(DispatcherPriority.Normal, new SetElementIsEnabledDelegate(SetElementIsEnabled), element, isEnabled); return; } element.IsEnabled = isEnabled; } 

添加另外30个代表并重新指定方法。

据我所知,没有类型安全的方法来完成所有线程调用的需要。 看起来这似乎很容易在控制库中引起注意。 我做错了什么,如果没有,为什么微软会选择不处理控件中调用的线程?

那么你当然可以使它更简单。 首先,您不需要所有自己的单独委托类型 – 如果您使用的是.NET 3.5,则可以使用内置的Func<...>Action<...>委托,如果您使用的话不是你可以自己声明它们然后一般地使用它们。

您可能考虑的另一件事是编写辅助方法(作为扩展方法,如果您使用的是C#3),然后使用匿名方法(或lambda表达式):

 internal static void SetElementIsEnabled(UIElement element, bool isEnabled) { InvokeIfNecessary(element, delegate { element.IsEnabled = isEnabled; }); } 

辅助方法是:

 public static void InvokeIfNecessary(UIElement element, MethodInvoker action) { if (element.Dispatcher.Thread != Thread.CurrentThread) { element.Dispatcher.Invoke(DispatcherPriority.Normal, action); } else { action(); } } 

(您可能还应该包含BeginInvoke等效项。除非我需要集合点,否则我通常更喜欢BeginInvoke 。)

简单地说,出于性能原因。 为什么每个GUI应用程序只有那些multithreading需要它时才能承担编组代码的性能影响?

此外,您可以将应用程序设计为具有较少的跨线程聊天,因此需要较少的调用。

此外,您的代码不是特别有效。 更好的方法是:

 if ( InvokeRequired ) { Invoke(new MethodInvoker(this.Function)); } else { // do code } 

编辑 :我想我的代码更适用于Windows Forms,而你的代码是WPF,但目的是相同的。 Windows要求由于线程本地存储问题而在创建控件的线程上发生所有控制更新。 而这并不适用于所有用途。

别忘了lambdas:

 int myParam = 5; Dispatcher.BeginInvoke((Action)(() => SomeMethod(myParam))); 

调度程序上还有一个隐藏的intellisense方法:

 if(Dispatcher.CheckAccess()) DoSomething();