小故事:我正在设计一个软件来验证CAD应用程序中的一些东西。当我尝试并行时,它只在WPF中变得非常慢。
长话短说:我有一个可以向我的库(.dll)提问的软件,这个库也是我制作的,而且这个库可以与我的计算机辅助设计软件(Zuken的E3.Series)进行通信。
我的软件最初是用WinForms制作的,一切都很好,但我认为界面会因为绑定而真正受益于WPF。所以我去翻译了它,但发现它要慢得多。所以我做了两个小项目来找出它变慢的地方。以下是结果,但我找不到原因:
这段代码和Winforms一样快(3.5秒):
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
Stopwatch timer = new Stopwatch();
timer.Start();
List<Wire> wires = e3.Project.Wires;
timer.Stop();
MessageBox.Show("WPF " + wires.Count + " in " + timer.Elapsed);
}但当我这样做时,它是(12秒):
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
Stopwatch timer = new Stopwatch();
timer.Start();
List<Wire> wires = e3.Project.Wires;
timer.Stop();
MessageBox.Show("WPF " + wires.Count + " in " + timer.Elapsed);
});
}这与BackgroundWorker完全相同。
我需要使用Task.Run和Parallel.ForEach,因为我有很多长时间的任务需要并行化。当我切换到Parallel.ForEach时,我的WinForms应用程序的速度提高了5到6倍,所以我不想因为切换到WPF而失去这一优势。
我看到我的CPU在空的WPF窗口中运行得更高,所以可能是没有足够的CPU让我的CAD应用程序工作并回答我的dll?
我想我在VS2015的CPU使用率分析器中发现的是,实际上是从我的库到我的计算机辅助设计软件的COM调用,由于我的应用程序而变得很慢。
发布于 2017-01-25 13:30:57
WinForm和WPF应用程序UI都在静态线程单元(STA)模型中运行。您提到使用Task.Run或后台工作线程都会降低性能。由于这两个组件都创建了多线程单元(MTA)线程,因此如果在STA中创建COM组件,则问题可能是由于封送处理造成的。有关更多信息,请参阅Understanding and Using COM Threading Models的“混合模型开发”部分。
您可以尝试创建一个STA线程,并在该线程上运行代码。
Thread t = new Thread(ThreadWorkMethod);
t.SetApartmentState(ApartmentState.STA);
t.Start();发布于 2017-01-25 10:35:42
首先,您不应该在线程池中被称为MessageBox.Show,因为它们没有设置为用户界面线程。
其次,确保e3.Project.Wires属性也不执行任何用户界面操作。
第三,尝试使用以下方法为线程池排队工作...
ThreadPool.QueueUserWorkItem(ThreadProc, e3);像这样使用...implementing方法...
static void ThreadProc(Object stateInfo)
{
??? e3 = (???)stateInfo;
Stopwatch timer = new Stopwatch();
timer.Start();
List<Wire> wires = e3.Project.Wires;
timer.Stop();
Console.WriteLine("WPF " + wires.Count + " in " + timer.Elapsed);
}显然,您需要将传入参数转换为正确的类型。
https://stackoverflow.com/questions/41842172
复制相似问题