【问题标题】:Control.Invoke method not returningControl.Invoke 方法不返回
【发布时间】:2014-10-06 22:23:50
【问题描述】:

我正在尝试并行化我的代码以使其运行得更快。到目前为止,都是头疼的问题,没有结果。

我想同时更新几个DataGridView:

    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, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
  • mscorlib.dll!System.Threading.WaitHandle.WaitOne(int 毫秒超时,布尔 退出上下文)
  • System.Windows.Forms.dll!System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle 等待句柄)
  • System.Windows.Forms.dll!System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control 调用者,System.Delegate 方法,object[] args,bool 同步)
  • System.Windows.Forms.dll!System.Windows.Forms.Control.Invoke(System.Delegate 方法,对象[] 参数)

他们为什么卡住了?

【问题讨论】:

    标签: c# .net-4.0


    【解决方案1】:

    我假设您从 UI 线程调用 Parallel.Invoke。如果是这样,那就是问题所在。

    Parallel.Invoke 阻塞,直到所有调用完成...这意味着您阻塞了 UI 线程。您正在启动的任务无法完成,因为 Control.Invoke 会阻塞直到 UI 线程上的调用完成 - 所以您的子任务正在等待 UI 线程可用以更新UI,但您的 UI 线程正在等待所有子任务完成。

    可以通过使用BeginInvoke 而不是Invoke 来解决此问题(无论如何您可能都想这样做),但在UI 线程中使用Parallel.Invoke 从根本上来说是个坏主意,正是因为它阻塞了。

    【讨论】:

    • System.Threading.Tasks.Task.Run(Action) 会起作用,还是我会遇到同样的问题?
    • @PierreGardin yes Task.Run(Action) 只要你不在 UI 线程中等待它就可以工作。
    • @PierreGardin:是的,这会起作用 - 因为调用 Task.Run 不会阻塞等待任务完成。
    猜你喜欢
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    • 2023-03-09
    • 2016-03-02
    • 2016-07-01
    • 1970-01-01
    • 2012-02-08
    • 2014-10-22
    相关资源
    最近更新 更多