2017-01-25 2 views
3

Рассказ: Я разрабатываю программное обеспечение для проверки некоторых вещей в приложении САПР. Когда я пытаюсь параллелизм, он очень медленный в WPF.C# Task.Run замедляет мою программу wpf

Длинная история: У меня есть мое программное обеспечение, которое задает вопросы о моей библиотеке (DLL), которые я также сделал, и эта библиотека взаимодействует с моим программным обеспечением САПР (E3.series from Zuken).

Мое программное обеспечение было первоначально создано в WinForms, и все было хорошо, но интерфейс, который, как я думал, действительно выиграет от WPF из-за привязки. Поэтому я пошел и перевел это, но обнаружил, что это медленнее. Так что я сделал 2 мини-проекта, чтобы найти, где он становится намного медленнее. Вот результаты, и я не могу найти, почему:

Этот код так же быстро, как 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, потому что у меня много длинных задач для распараллеливания. Мое приложение WinForms получилось в 5-6 раз быстрее, когда я изменился на Parallel.ForEach, поэтому я не хочу потерять эту выгоду для перехода на WPF.

Я вижу, что мой процессор работает выше с пустым окном WPF, так что может быть, что для моего приложения САПР не хватает процессора для работы и ответа на мою DLL?

Что я думаю, что с помощью анализатора использования процессора в VS2015 я обнаружил, что это действительно COM-вызов из моей библиотеки для моего программного обеспечения САПР, которое намного медленнее из-за моего приложения.

+0

_would действительно извлечь выгоду из WPF из-за binding_ - 'поддержку Winforms' связывания, а также – Fabio

ответ

1

И пользовательский интерфейс приложения WinForm и WPF работает в модели Static Thread Apartment (STA). Вы отмечаете, что использование рабочего стола Task.Run или Background снижает производительность. Поскольку оба эти типа создают потоки многопоточной квартиры (MTA), проблема может быть вызвана маршалингом, если COM-компонент создан в STA. Дополнительную информацию см. В разделе «Разработка смешанной модели» от Understanding and Using COM Threading Models.

Вы можете попробовать создать поток STA и запустить свой код.

Thread t = new Thread(ThreadWorkMethod); 
t.SetApartmentState(ApartmentState.STA); 
t.Start(); 
+1

не удалось сделать то, что вы сказали, потому что я не знал, как дождаться завершения этого потока, но на end, создав свой объект E3 в моем новом потоке, сделал это для меня вместо того, чтобы создавать и использовать его в своем новом потоке. – user3704628

+0

@ user3704628, как правило, вы не ждете окончания потока, а скорее предоставляете такой механизм, как повышение события, чтобы сигнализировать о его завершении. Другим вариантом является передача делегата для вызова в потоке пользовательского интерфейса, который указывает на способ выполнения; это действительно более прямой метод, в отличие от события, которое является не чем иным, как конфетным способом для вызова делегата. В любом случае, я рад, что обратился к нему, что решил вашу проблему, поскольку я знал о возможности этого, но так и не испытал этого. Это также поможет другим, если вы можете указать название своего программного обеспечения САПР в своем оригинальном посте. – TnTinMn

0

Прежде всего, вы не должны называться MessageBox.Show внутри пула потоков, потому что они не настраиваются как потоки пользовательского интерфейса.

Во-вторых, убедитесь, что свойство e3.Project.Wires не выполняет никаких действий с пользовательским интерфейсом.

В-третьих, попробуйте использовать следующий метод в очередь работы для пула потоков ...

ThreadPool.QueueUserWorkItem(ThreadProc, e3); 

... реализации метода, как это ...

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

с этим кодом, мне удалось получить мои WinForms так медленно, как мой WPF окна (11 сек), и я также видел, что е3. Project.Wires называет тонну времени программным обеспечением cad, и это нормально, но 1 вызов занимает 25 мс вместо 4 мс, когда я использую этот метод, поэтому проблема действительно является побочным эффектом, который заставляет программное обеспечение САПР 6 раз медленнее отвечать. – user3704628

+1

'ThreadPool.QueueUserWorkItem' такой же, как' Task.Run' без преимуществ 'async-await' – Fabio

Смежные вопросы