首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# Task.Run减慢我的wpf程序

C# Task.Run减慢我的wpf程序
EN

Stack Overflow用户
提问于 2017-01-25 09:55:48
回答 2查看 956关注 0票数 4

小故事:我正在设计一个软件来验证CAD应用程序中的一些东西。当我尝试并行时,它只在WPF中变得非常慢。

长话短说:我有一个可以向我的库(.dll)提问的软件,这个库也是我制作的,而且这个库可以与我的计算机辅助设计软件(Zuken的E3.Series)进行通信。

我的软件最初是用WinForms制作的,一切都很好,但我认为界面会因为绑定而真正受益于WPF。所以我去翻译了它,但发现它要慢得多。所以我做了两个小项目来找出它变慢的地方。以下是结果,但我找不到原因:

这段代码和Winforms一样快(3.5秒):

代码语言:javascript
复制
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秒):

代码语言:javascript
复制
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.RunParallel.ForEach,因为我有很多长时间的任务需要并行化。当我切换到Parallel.ForEach时,我的WinForms应用程序的速度提高了5到6倍,所以我不想因为切换到WPF而失去这一优势。

我看到我的CPU在空的WPF窗口中运行得更高,所以可能是没有足够的CPU让我的CAD应用程序工作并回答我的dll?

我想我在VS2015的CPU使用率分析器中发现的是,实际上是从我的库到我的计算机辅助设计软件的COM调用,由于我的应用程序而变得很慢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-25 13:30:57

WinForm和WPF应用程序UI都在静态线程单元(STA)模型中运行。您提到使用Task.Run或后台工作线程都会降低性能。由于这两个组件都创建了多线程单元(MTA)线程,因此如果在STA中创建COM组件,则问题可能是由于封送处理造成的。有关更多信息,请参阅Understanding and Using COM Threading Models的“混合模型开发”部分。

您可以尝试创建一个STA线程,并在该线程上运行代码。

代码语言:javascript
复制
Thread t = new Thread(ThreadWorkMethod);
t.SetApartmentState(ApartmentState.STA);
t.Start();
票数 1
EN

Stack Overflow用户

发布于 2017-01-25 10:35:42

首先,您不应该在线程池中被称为MessageBox.Show,因为它们没有设置为用户界面线程。

其次,确保e3.Project.Wires属性也不执行任何用户界面操作。

第三,尝试使用以下方法为线程池排队工作...

代码语言:javascript
复制
ThreadPool.QueueUserWorkItem(ThreadProc, e3);

像这样使用...implementing方法...

代码语言:javascript
复制
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);
}

显然,您需要将传入参数转换为正确的类型。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41842172

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档