2010-02-24 85 views
4

当我尝试从自定义面板控件读取属性时出现此错误。该属性返回面板中文本框的值。如何读取从另一个线程返回文本框控件值的属性?我的房产代码样本如下。我不担心二传手。当读取属性时,跨线程操作无效

以下是eaxct错误消息: 跨线程操作无效:从其创建线程以外的线程访问控制''。

public string Header 
{ 
get 
{ 
    return _HeaderComboBox.Text; 
} 
set 
{ 
    _HeaderComboBox.Text = value; 
} 
} 
+0

看:这可以通过使用Invoke方法来完成 http://stackoverflow.com/questions/2316631/how-to-make-thread-safe-calls-to-windows-forms-控制 – n535 2010-02-24 22:25:22

回答

6

MSDN sample using BeginInvoke

这是我将如何实现基于吸气片断您发布的示例:

public string Header { 
    get { 
     string text = string.Empty; 
     _HeaderComboBox.BeginInvoke(new MethodInvoker(delegate { 
      text = _HeaderComboBox.Text; 
     })); 
     return text; 
    } 

    set { 
     _HeaderComboBox.Text = value; 
    } 
} 

有更优雅的方式,然而,这对你是一个普通的例子。

+1

他没有说他在哪个平台上。此链接适用于WinForms;对于WPF,请改用Dispatcher.BeginInvoke。 – itowlson 2010-02-24 22:28:22

+1

谢谢。我认为这解决了我的问题。唯一的问题是它一直返回一个空字符串。正在使用调用而不是BeginInvoke正确的方式来做到这一点? – 2010-02-24 23:18:20

+0

如果它返回一个空字符串,那么你没有设置文本属性。我在一个测试项目中做了这件事,以确保它能够工作 - 并且它确实返回了文本属性。 – IAbstract 2010-02-25 00:01:09

3

您需要编组回调到UI线程才能访问该属性。

在.NET 2.0之前,您必须调用Control类的Invoke method才能将调用编组为Text proprety。

在.NET 2.0及之后,如果您的后台线程有权访问UI线程的SynchronizationContext,则可以拨打Send method以将回调编组回UI。

请注意,如果你没有等待调用的结果(如你在这里做的,因为你要调用的Text属性的结果),你可以在控制调用BeginInvokePost和SynchronizationContext分别。

0

你必须将你的跨线程代码外包给一个单独的方法,做一个委托,然后Invoke它在你想改变的线程中的一个控件上。你也可以使用闭包而不是委托+方法。

2

您不能在除UI线程A.K.A以外的任何线程上访问WinForms控件。它是由于交叉线程问题,竞争条件等而创建的。为了解决这个问题,你必须运行你想在UI线程上运行的任何命令。这里

public void InvokeExample() 
{ 
    if (InvokeRequired) 
    { 
     // Invoke this method on the UI thread using an anonymous delegate 
     Invoke(new MethodInvoker(() => InvokeExample())); 
     return; 
    } 

    string header = Control.Header; 
}