C# C Func委托引发线程异常

C# C Func委托引发线程异常,c#,C#,所以,也许我误解了Func的用法,但是 Func<ComboBox, string> getCurrentValue = s => s.SelectedValue.ToString(); 从我的Workerthread调用getCurrentValuecb_消息_类型时创建线程错误。 获得组合框选定值的最佳解决方案是什么 非常感谢,, 雷特 编辑 MSDN lambda表达式的基础类型是泛型Func委托之一。这使得可以将lambda表达式作为参数传递,而无需将其显式分配给委托

所以,也许我误解了Func的用法,但是

Func<ComboBox, string> getCurrentValue = s => s.SelectedValue.ToString();
从我的Workerthread调用getCurrentValuecb_消息_类型时创建线程错误。 获得组合框选定值的最佳解决方案是什么

非常感谢,, 雷特

编辑 MSDN


lambda表达式的基础类型是泛型Func委托之一。这使得可以将lambda表达式作为参数传递,而无需将其显式分配给委托。

由于windows控件具有线程关联性,因此有两个选项:

在执行线程代码之前查询此数据,例如,将其作为状态传递给工作程序 通过Control.Invoke在worker中查询它 由于第一个变量很小,我将给出第二个使用捕获变量的示例:

object value = null;
yourCombo.Invoke((MethodInvoker) delegate {value=yourCombo.SelectedValue;});
string s = value.ToString();
这里,委托{…}内的位发生在UI线程上,即使它周围的代码在工作线程上。您可以在func内部混合上述内容,也可以在切换线程后调用整个func。

您需要调用Control.Invoke(使用该委托调用),或者让委托本身调用它。 使用lambda表达式不会改变Windows窗体的线程要求-它只是使创建委托更容易

您可能希望使用一种方便的方法来执行此操作:

// (Untested)
public static Func<TControl, TResult> WrapInvocation(Func<TControl,TResult> func)
    where TControl : Control
{
    return control => {
        return (TResult) control.Invoke(func);
    };
}
用作:

Func<ComboBox, string> getCurrentValue = s => s.SelectedValue.ToString();
getCurrentValue = WrapInvocation(getCurrentValue);

然后可以从任何线程调用getCurrentValuecomboBox。

问题是UI控件只能在UI线程上使用

您需要在另一个线程中调用Invoke方法,如下所示:

Func<ComboBox, string> getCurrentValue =
    s => s.Invoke(new Func<object>(() => s.SelectedValue)).ToString();

Invoke方法接受委托并在UI线程上执行它。

一般来说,您不能从创建UI控件的线程以外的线程访问UI控件。要克服这一问题,您必须检查相关控件和分支上的ISynchronizeInvoke.InvokeRequired、调用委托等,或者使用SynchronizationContext。第一个选项非常麻烦,而第二个选项非常优雅:

var synchronizationContext = WindowsFormsSynchronizationContext.Current;
string currentValue = "";    

synchronizationContext.Send(
    () => currentValue = getCurrentValue(comboBox), 
    null);

如果线程只是在读取ComboBox,那么如果可行的话,最好的选择可能是在线程上有一个事件处理程序,它可以在ComboBox值发生任何更改时获取该值,然后通过可以从任何线程读取的属性公开该值