所以,也许我误解了Func的用法但是
Func<ComboBox, string> getCurrentValue = s => s.SelectedValue.ToString();
从我的Workerthread调用getCurrentValue(cb_message_type)
时创建一个线程错误。
什么是获得Combobox选定值的最佳解决方案?
非常感谢,
rAyt
修改
MSDN
“lambda表达式的基础类型是通用Func委托之一。这使得可以将lambda表达式作为参数传递,而无需将其明确地分配给委托。”
答案 0 :(得分:5)
由于Windows控件具有线程关联性,因此您有两个选项:
由于第一个是微不足道的,我将使用捕获的变量给出第二个示例:
object value = null;
yourCombo.Invoke((MethodInvoker) delegate {value=yourCombo.SelectedValue;});
string s = value.ToString();
这里delegate {...}
内的位发生在UI线程上,即使它周围的代码在工作线程上。您可以将上面的内部混合到您的func中,或者在切换线程后调用整个函数。
答案 1 :(得分:2)
您需要使用该委托调用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);
然后你可以从任何线程中调用getCurrentValue(comboBox)
。
答案 2 :(得分:1)
问题是UI控件只能在UI线程上使用
您需要在另一个线程中调用Invoke
方法,如下所示:
Func<ComboBox, string> getCurrentValue =
s => s.Invoke(new Func<object>(() => s.SelectedValue)).ToString();
Invoke
方法接受一个委托并在UI线程上执行它。
答案 3 :(得分:1)
一般来说,您无法从创建它们之外的线程访问UI控件。要解决这个问题,您必须检查有问题的控件上的ISynchronizeInvoke.InvokeRequired
和分支,调用委托等,或使用SynchronizationContext
。第一种选择非常麻烦,而第二种选择非常优雅:
var synchronizationContext = WindowsFormsSynchronizationContext.Current;
string currentValue = "";
synchronizationContext.Send(
() => currentValue = getCurrentValue(comboBox),
null);
答案 4 :(得分:0)
如果线程只是简单地读取ComboBox,那么最好的选择(如果可行的话)可能是在线程上有一个事件处理程序,它在任何时候更改时都会获取ComboBox值,然后通过可以从中读取的属性公开该值任何线程。