使用parallel.Invoke运行后台工作后更新UI

时间:2010-12-17 11:44:18

标签: c# parallel-processing

我正在使用Parallel.Invoke运行繁重的后台工作,在所有处理完成后我返回方法,再次返回,调用下一个方法来利用计算出的数据我得到错误: 跨线程操作无效:控制''从创建它的线程以外的线程访问。

但是我已经从Parallel.Invoke创建的线程返回到首先调用它的线程。控件不会恢复到它启动的线程是否正常?我怎样才能确保这确实发生?

代码:

public void TopMethod()
        {
            Calculate(4);
            UpdateGui();
        }

        public void Calculate(int depth)
        {
            Recursive(depth);
        }

        public void Recursive(int depth)
        {
            if (depth > 0)
                System.Threading.Tasks.Parallel.Invoke(
                            delegate { Recursive(depth - 1); });
        }

        public void UpdateGui()
        {
            CalculateOhter(); // Works fine.
            controlElement.Focus(); // Causes exception
        }

编辑: 我知道Control.Invoke但这将是一个丑陋的解决方案(不想在每个控件中存储委托),程序需要等待所有计算完成才能继续。所以如果我能以某种方式强制控制返回到我最初开始的线程会更好。

4 个答案:

答案 0 :(得分:1)

您需要从创建该控件的线程访问控件/窗口。使用Control.InvokeControl.InvokeRequired

答案 1 :(得分:0)

可怕的方法是将Control.CheckForIllegalCrossThreadCalls设置为false。它应该摆脱你的错误,但这不是好设计。

当控件的创建线程以外的线程试图访问该控件的方法或属性之一时,会出现问题,这通常会导致不可预测的结果。

答案 2 :(得分:0)

Control.Invoke的示例涉及存储委托,这可以在不为每个控件存储委托的情况下完成吗?所以传递我需要调用的方法作为Invoke调用的参数(试过这个,但不能让它工作)。

程序需要等待所有计算完成才能继续,所以如果我能以某种方式强制控制返回到我最初开始的线程,那就更好了。

我不明白为什么在默认情况下不会发生这种情况,为什么它不只是在一切都完成后返回它开始的线程?

答案 3 :(得分:0)

解决了它,结果我创建了一个单独的线程来调用给定的代码,有点愚蠢:P