在新线程c#windows应用程序中运行一个函数

时间:2012-12-28 11:58:10

标签: c# winforms multithreading

我正在研究在window_load上调用函数populate()的应用程序

此功能执行大约需要1分钟才能完成。我想让这个函数在单独的线程中调用。

我正在使用以下代码

Thread thread = new Thread(PopulateAndDrawGraph);
        thread.Start();

在此函数的最后一行是

nodeXlControl1.DrawGraph(真);

此处发生异常

调用线程无法访问此对象,因为另一个线程拥有它。

实际发生了什么错误

7 个答案:

答案 0 :(得分:2)

您只能从创建控件的同一个线程中访问UI控件,这通常是UI线程本身。

您需要以能够识别线程的方式更改代码。

这是一篇发表在MSDN杂志上的精彩文章:Give Your .NET-based Application a Fast and Responsive UI with Multiple Threads,它将详细解释你如何做你想做的事。

这篇文章有点陈旧,但同样的原则仍然适用。

我认为较新的C#语言功能 - 比如新的async / await关键字 - 应该可以让您的任务更轻松。

但请记住,仍然存在访问UI控件的相同旧限制。没有办法理解文章中描述的基础知识。

答案 1 :(得分:1)

有两种方法可以解决这个问题,一种正确的方式和另一种方式:

1:如果你想要一个好的工作解决方案,那么这应该可以解决问题,..

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the 
        // calling thread to the thread ID of the creating thread. 
        // If these threads are different, it returns true. 
        if (this.textBox1.InvokeRequired)
        {   
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.textBox1.Text = text;
        }
    }

msdn.microsoft.com/en-us/library/ms171728.aspx

2:但如果你想要一个快速的解决方案而不保证它能正常工作,只需设置这个变量: Control.CheckForIllegalCrossThreadCalls = False

答案 2 :(得分:0)

问题是,任何UI交互必须发生在应用程序的主线程中。我的建议是你在单独的线程中绘制计算,但是在一个对象中收集你的结果。线程完成后,您可以从该对象中提取结果,并将其放置在nodeXlControl1。

可悲的是,我不知道有关你的目标的细节,解决方案的总和就是这个。 如果你能告诉我这方面的更多细节,我可以进一步帮助你。

答案 3 :(得分:0)

在这里查看this article (How to: Make Thread-Safe Calls)。它解释了有关跨线程调用的所有相关项目。我还建议您在c#中查看“任务”的概念。这是一个写得很好的lib,可以帮助你处理并行性和类似的概念!

答案 4 :(得分:0)

由于您尝试从线程访问UI元素,因此需要调用Invoke。所以在PopulateAndDrawGraph你应该有:

Invoke((Action)(() =>
{
    nodeXlControl1.DrawGraph(true);
}));

答案 5 :(得分:0)

除了创建此控件的线程之外,您无法从任何其他线程访问UI控件(您只能从主UI线程访问/更改UI控件属性)。通过此链接,我希望这能让您清楚Cross-thread operation not valid

答案 6 :(得分:0)

我在c#中使用了BackgroundWorker类。