![](/img/trans.png)
[英]“Cross-thread operation is not valid” exception when trying to get value of comboBox in Backgroundworker
[英]“Cross-thread operation is not valid” exception when trying to get value of comboBox
"Cross-thread operation is not valid" exception
我经历了很多次此异常,但所有那些时候我都在设置控件的值。 那个时候我解决了使用一个名为SetControlPropertyThreadSafe()
的函数,该函数仅由stackoverflow.com上的某人建议。 但是这次我在尝试获取comboBox的值时遇到此异常。 这是代码:
string cat;
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text.Trim().Length > 20)
{
System.Threading.Thread t = new System.Threading.Thread(addQuickTopic);
t.Start();
}
else
MessageBox.Show("The length of the title must be greater than 20", "Title length invalid", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
public string tTitle="";
void addQuickTopic()
{
Global.SetControlPropertyThreadSafe(button1, "Text", "Working...");
Global.SetControlPropertyThreadSafe(button1, "Enabled", false);
Topic t = new Topic();
t.setTitle(textBox1.Text);
t.setDescription(" ");
t.setDesID(Global.getMd5Hash(Common.uid+DateTime.Today.ToString()+DateTime.Today.Millisecond.ToString()));
t.setUsrID(Common.uid);
t.setReplyToID("");
t.setConDate("0");
cat = CategoryList.SelectedValue.ToString();
正如您所看到的,我直接获取textBox1.Text而不应用任何线程安全操作。 但是在尝试获取comboBox的选定值时的最后一行,我得到了这个异常。 所以任何人都可以建议我在这种情况下做什么? 以下是我的线程安全功能的代码,用于设置控件的值:
public static void SetControlPropertyThreadSafe(Control control, string propertyName, object propertyValue)
{
try
{
if (control.InvokeRequired)
{
control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new object[] { control, propertyName, propertyValue });
}
else
{
control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { propertyValue });
}
}
catch (Exception)
{ }
}
我是否需要创建类似的get
函数? 或任何其他解决方案?
现在,您从TextBox
获取值,通过: t.setTitle(textBox1.Text);
。 这也将失败。
我是否需要创建类似的get函数? 或任何其他解决方案?
是的,你需要一个获得的选择。 我建议不要使用反射和文本,然后重做这个以使用泛型方法和lambdas。
public static void SetControlPropertyThreadSafe<T>(T control, Action<T> action) where T : Control
{
if (control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action();
}
}
这将允许你写这个强类型,即:
Global.SetControlPropertyThreadSafe(button1, b => b.Text = "Working...");
您还可以创建一个强类型的get方法:
public static U GetControlPropertyThreadSafe<T,U>(T control, Func<T,U> func) where T : Control
{
if (control.InvokeRequired)
{
return (U)control.Invoke(func, new object[] {control});
}
else
{
return func(control);
}
}
然后让你写:
t.setTitle(Global.GetControlPropertyThreadSafe(textBox1, t => t.Text));
您还可以使用相同的方法来获取和设置组合框项目。
您需要一个类似的get函数,如果需要,它会调用Invoke。 这取决于GUI的线程模型,该模型声明与GUI交互的所有方法只应由GUI线程调用。
如果你正在尝试阅读,写作或做任何其他事情,这并不重要。 如果您不在GUI线程上,则必须使用Invoke。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.