2014-10-06 6 views
0

Я пытаюсь распараллелить свой код, чтобы он работал быстрее. До сих пор это были все головные боли и никаких результатов.Метод Control.Invoke не возвращается

Я хочу обновить несколько DataGridViews одновременно:

Parallel.Invoke(
     () => updateDgv1(), 
     () => updateDgv2(), 
     () => updateDgv3() 
    ); 

Я попытался с помощью простой (но, вероятно, не оптимальный) способ, рекомендованный везде в Интернете (как здесь http://msdn.microsoft.com/en-us/library/ms171728(v=vs.85).aspx).

private void updateDgv1() { 
    /* some stuff */ 

    assignValue(this.dgv1, colPos, rowPos, value); /* in a loop */ 
    } 

    delegate void AssigneValueCallback(DataGridView dgv, int columnPos, int rowPos, string valeur); 

    public void assignValue(DataGridView dgv, Form form, int columnPos, int rowPos, string value) 
    { 
     if (dgv.InvokeRequired) 
     { 
      AssigneValueCallbackd = new AssigneValueCallback(assignValue); 
      dgv.Invoke(d, new object[] { dgv, columnPos, rowPos, value }); 
     } 
     else 
     { 
      dgv[columnPos, rowPos].Value = value; 
     } 
    } 

Основной поток застревает на «Parallel.Invoke (...)» вызов, ожидая другие потоки, чтобы закончить.

нити, созданные "Parallel.Invoke (...)" застревают в данный момент:

  • mscorlib.dll System.Threading.WaitHandle.InternalWaitOne (System.Runtime.InteropServices.SafeHandle waitableSafeHandle, долго millisecondsTimeout, BOOL hasThreadAffinity, BOOL exitContext)
  • mscorlib.dll! System.Threading.WaitHandle.WaitOne (INT millisecondsTimeout, BOOL exitContext)
  • System.Windows.Forms.dll! System.Windows. формы .Control.WaitForWaitHandle (System.Threading.WaitHandle WaitHandle)
  • System.Windows.Forms.dll! System.Windows.Forms.Control.MarshaledInvoke (System.Windows.Forms.Control вызывающий метод System.Delegate, объект [] арг, BOOL синхронные)
  • System.Windows.Forms.dll! System.Windows.Forms.Control.Invoke (System.Delegate метод, объект [] арг)
  • и т.д.

Почему они застряли?

ответ

4

Я предполагаю, что вы вызываете Parallel.Invoke из потока пользовательского интерфейса. Если да, это проблема.

Parallel.Invoke блокирует до тех пор, пока все вызовы не закончатся ... что означает, что вы блокируете поток пользовательского интерфейса. Задачи, которые вы запускаете , не могут завершаться, потому что Control.Invoke блокируется до тех пор, пока не завершится вызов по потоку пользовательского интерфейса, поэтому ваши подзадачи ждут появления потока пользовательского интерфейса для обновления пользовательского интерфейса, но ваш поток пользовательского интерфейса ожидая завершения всех подзадач.

Вы могли просто исправить это с помощью BeginInvoke вместо Invoke (и вы можете сделать это в любом случае), но это принципиально плохая идея использовать Parallel.Invoke в потоке пользовательского интерфейса, именно потому, что блоки.

+0

Работает ли System.Threading.Tasks.Task.Run (Action), или я столкнулся бы с той же проблемой? –

+0

@PierreGardin yes Task.Run (Action) будет работать до тех пор, пока вы не дожидаетесь его в потоке пользовательского интерфейса. – Letseatlunch

+0

@PierreGardin: Да, это сработало бы - потому что вызов 'Task.Run' не блокирует ожидания завершения задачи. –

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