2012-12-28 52 views
2

我的应用程序,它呼吁window_load运行在新线程的C#Windows应用程序的功能

这个函数执行约需要1分钟才能完成的功能填入()工作。我想让这个函数在单独的线程中被调用。

我使用下面的代码

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

在最后一行此功能

nodeXlControl1.DrawGraph(真);

这里发生异常

,因为不同的线程拥有它调用线程不能访问该对象。

其实是自己做错了什么发生

+0

ca你分享该异常的堆栈跟踪? – Arshad

回答

0

我已经在c#中使用BackgroundWorker类。

0

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

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

2

您只能从创建控件的相同线程(通常是UI线程本身)访问UI控件。

您将需要更改您的代码,使其变为线程感知。

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

该文章有点旧,但仍然适用相同的原则。

我想新的C#语言功能 - 如新的async/await关键字 - 应该让您的任务更容易一些。

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

0

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

+1

链接只有答案不是很好的答案。我知道你已经链接到MSDN,但发生了变化,如果链接不好,这个答案将变得毫无用处。 – ChrisF

+0

@ChrisF +1 ...注意到并编辑! – Leonardo

0

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

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

有2种方式来处理这个问题,以正确的方式和另一种方式:

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

0

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

相关问题