2011-04-01 32 views
22

我试图从非线程以外的线程上创建它的读取combobox.Text但我得到的错误:如何从线程以外的线程读取组合框?

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll

Additional information: Cross-thread operation not valid: Control 'levelsComboBox' accessed from a thread other than the thread it was created on.

我用.Invoke之前,但只设置属性,怎么能我用它来阅读combobox.Text?因为.Invoke返回void,我需要一个字符串。或者还有另一种方法可以在没有调用的情况下执行它?

+0

我认为这是对[如何获得返回值时的BeginInvoke /调用被称为重复C#](http://stackoverflow.com/questions/2214002/how-to-get-return-value-when-begininvoke-invoke-is-called-in-c) – 2011-04-01 16:30:49

回答

44

你可以这样说:

this.Invoke((MethodInvoker)delegate() 
    { 
     text = combobox.Text; 
    }); 
+1

我有2天搜索此解决方案。 thnx – Florjon 2012-03-01 11:46:12

+0

非常棒。它帮助我在C#中实现Observer模式。 – Mythul 2013-06-02 14:10:21

+0

太棒了!上午3点帮助我。抓我的脑袋,记住这句话... – 2014-04-13 00:42:27

2

最简单的解决方案是使用BackgroundWorker类在另一个线程上执行工作,同时仍能够更新UI(例如,在报告进度或任务完成时)。

17

您仍然可以使用Invoke并将其读取到本地变量中。

事情是这样的:

string text; 

this.Invoke(new MethodInvoker(delegate() { text = combobox.Text; })); 

由于Invoke是同步的,你有保证text变量将包含组合框的文本值返回后。

4

最短的方法是:

string text; 
this.Invoke(() => text = combobox.Text); 
+0

这似乎并不奏效。请参阅链接:http://connect.microsoft.com/VisualStudio/feedback/details/395813/system-delegate-is-not-a-delegate-type – Bill 2012-07-21 15:14:43

+0

@YongkeBillYu链接要求登录。我不明白为什么它不会工作,但它应该与接受的解决方案一样。 – 2016-04-14 14:05:25

+0

@Igor有一个警告,虽然:编译器抱怨的代码,除非[你把它转换成动作类型](http://stackoverflow.com/questions/411579/why-must-a-lambda-expression-becast - 当提供的作为一种-纯代表参数)。请编辑代码。 – 2016-04-14 14:25:30

相关问题