【发布时间】:2013-11-11 13:54:29
【问题描述】:
我正在增强一个通过 web 服务与 SalesForce CRM 交互的 c# win 表单应用程序。
我有以下代码可以对表单上的标签进行“线程安全”更新:
delegate void SetTextCallback(string text);
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.lblAccessStatus.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.lblAccessStatus.Text = text;
this.lblAccessStatus.Refresh();
}
}
我的表单(称为SFDetachifier.cs)有一个执行按钮,它获取两个日历控件的日期,然后调用:
lblAccessStatus.Visible = true;
picProgress.Visible = true;
string fromDate = dtManualFromDate.Value.ToString("yyyy-MM-dd") + fromTime;
string toDate = dtManualToDate.Value.ToString("yyyy-MM-dd") + toTime;
string[] arg = new string[] { "S1", fromDate, toDate };
SFCtrl._SessionLog.Append("Manual detach requested on " + SFOrgName + "\n");
SFCtrl._SessionLog.Append("Date range requested: " + fromDate + " to " + toDate + "\n");
bgProcessing_Production.RunWorkerAsync(arg);
bgProcessing_Production 具有以下后台工作人员代码,其中包括对 setText 的调用
private void bgProcessing_Production_DoWork(object sender, DoWorkEventArgs e)
{
String[] args = (String[])e.Argument;
e.Result = args[0];
// clear the datagrid view
gvTaskCases.DataSource = null;
//gvTaskCases.Rows.Clear();
//if (gvTaskCases.Rows.Count != 0)
// {
// gvTaskCases.Rows.Clear(); // .Update();
// }
SetText("login to SalesForce (on " + SFOrgName + ") ...please wait");
现在,当我运行我的应用程序时,我设置了一些日期,然后通过单击执行按钮执行上面的代码,它就可以正常工作(调用 SalesForce XML Web 服务)并将结果放入一个网格中。
一切正常,当我尝试再次运行该程序时出现问题(例如使用不同的日期)
然后我得到一个错误 'Cross-thread operation not valid: Control '' 从创建它的线程以外的线程访问。'
我不明白,我有委托设置?
我做错了什么 - 我猜当后台工作人员再次运行时,它会在新线程上运行,因此线程不安全。
请问我该如何解决这个错误?
【问题讨论】:
-
只是检查 -
gvTaskCases.DataSource = null;是否会导致异常? -
有趣的是错误信息中的控件名称是''
-
以上两个优点,但是,`gvTaskCases.DataSource = null;` 不是问题(尽管我在
setText调用上方的注释代码中确实遇到了该控件的一些线程安全问题 -
BeginInvoke 会解决问题吗?我不明白为什么,但你可以试一试
标签: c# .net winforms thread-safety