多线程WPF应用程序:Dispatcher Invoke.一种更有效的方式?

Spa*_*rky 8 c# wpf multithreading dispatcher

使用.NET 3.5

嗨,大家好,我正在为一个项目制作一个WPF应用程序,我只是看了一下Dispatcher和多线程的一些见解.我的计划的一个例子:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
                        () =>_aCollection.Add(new Model(aList[i], aSize[i]))));

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
                        () => _Data.Add(new DataPoint<double, double>(Id, aList[i]))));

 Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
                        () => _historical[0].Add(aList[i])));
Run Code Online (Sandbox Code Playgroud)

据我所知,当另一个线程访问除创建它之外的对象时,WPF不喜欢.然而,我认为必须有一个更好的方法,而不是让这么多的调度员调用,有人可能请至少把我推向正确的方向(如果有更好的解决方案).

干杯,Sparky

A.R*_*.R. 16

你可以从你的通话中减少冗长开始,即

Application.Current.Dispatcher.Invoke(() =>_aCollection.Add(new Model(aList[i], aSize[i])));
Run Code Online (Sandbox Code Playgroud)

我喜欢使用的另一个技巧是创建一个这样的快捷方法:

public static void UiInvoke(Action a)
{
  Application.Current.Dispatcher.Invoke(a);
}
Run Code Online (Sandbox Code Playgroud)

那么你甚至可以做更少的事情,如:

UiInvoke(() =>_aCollection.Add(new Model(aList[i], aSize[i])));
Run Code Online (Sandbox Code Playgroud)

使用dispatcher.Invoke()实际上就是如何将操作返回到UI线程,这可能是首先创建这些对象(_aCollection)的地方.如果有问题的项目没有与UI线程直接交互,那么您可以在不同的线程上创建/操作它们,从而无需使用调度程序.当然,这种方法可能会变得更加复杂,具体取决于您正在做什么.


Ada*_*son 13

最简单的方法是将所有三个调用合并为一个:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
                        () =>
                      {
                          _aCollection.Add(new Model(aList[i], aSize[i]);
                          _Data.Add(new DataPoint<double, double>(Id, aList[i]);
                          _historical[0].Add(aList[i])
                      }));
Run Code Online (Sandbox Code Playgroud)

  • @Sparky:您使用 `=&gt;` 运算符所做的就是创建一个 lambda 表达式,它是一种匿名委托类型。这些都是语法糖,编译器最终将其转换为普通实例(或有时是静态)方法。您可以在 lambda 表达式中执行您可以在普通函数中执行的任何操作(当它用作匿名委托时,就像这里一样),除了(可能;我没有检查)“ref”和“out”参数。 (2认同)

Cod*_*lla 6

如果您使用.Net 4.0,我会考虑使用System.Threading.Tasks.这似乎是延续的一个主要例子.

  • 当然会,因为你可以在后台线程上安排你的"后台"任务,然后在UI线程上继续"完成"它,如:`Task.ContinueWith(FinishMyStuff,TaskScheduler.FromCurrentSynchronizationContext)` (5认同)
  • @AdamRobinson嗯,他要求"洞察力"并且他没有提供任何限制,所以我提出了我认为最好的"想法".如果他选择的话,他可以自由地忽略它. (3认同)