[英]cannot make multiple thread safe calls to windows forms control
我正在增強通過Web服務與SalesForce CRM交互的ac#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
)具有一個execute按鈕,該按鈕接受兩個日歷控件的日期,然后調用:
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服務)並將結果放入網格中。
一切正常,當我嘗試再次運行該過程時(例如,使用不同的日期)會出現問題
然后,我得到一個錯誤“跨線程操作無效:從其他線程(不是在其上創建的線程)訪問的控件”。
我不明白,我有一個代表設置嗎?
我在做什么錯-我猜測當backround worker再次運行時,它將在新線程上運行,因此是線程不安全的。
請問如何解決此錯誤?
您可以使用匿名委托將事情縮短一些,如下所示:
private void removeGridDS()
{
this.gvTaskCases.Invoke((MethodInvoker)delegate
{
if (this.gvTaskCases.DataSource != null)
{
this.gvTaskCases.DataSource = null;
}
});
}
private void clear_gvTaskCases()
{
this.gvTaskCases.Invoke((MethodInvoker)delegate
{
if (this.gvTaskCases.Rows.Count != 0)
{
this.gvTaskCases.Rows.Clear();
}
});
}
現在,您不需要硬編碼的委托。 此外,您沒有使用傳入的布爾值。
這是我為了解決此問題而最終要做的事情,正如上面的注釋之一所建議的,它似乎是對控件gvTaskCases
的調用gvTaskCases
了錯誤,因此我在該控件上創建了線程安全方法調用太:
delegate void SetTextCallback(string text);
delegate void clear_gvTaskCasesCallback(bool clearIt);
delegate void remove_gvTaskCasesDSCallback( bool removeDS);
private void removeGridDS(bool removeDS)
{
// 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.gvTaskCases.InvokeRequired)
{
remove_gvTaskCasesDSCallback d = new remove_gvTaskCasesDSCallback(removeGridDS);
this.Invoke(d, new object[] { removeDS });
}
else
{
if (this.gvTaskCases.DataSource !=null)
{
this.gvTaskCases.DataSource=null;
}
}
}
private void clear_gvTaskCases(bool clearIt)
{
// 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.gvTaskCases.InvokeRequired)
{
clear_gvTaskCasesCallback d = new clear_gvTaskCasesCallback(clear_gvTaskCases);
this.Invoke(d, new object[] { clearIt });
}
else
{
if (this.gvTaskCases.Rows.Count != 0)
{
this.gvTaskCases.Rows.Clear();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.