[英]Problems trying to pass events between threads
我需要對多線程編程模型做一些澄清,因為很少我必須處理它(大多數時候我都在進行網絡編程)。
我有一個我在C#中創建的程序,基本上它是一個數據監視器,並在數據庫上執行匯集每個特定的時間,比方說1分鍾。
這個應用程序是如何相對簡單的我決定使用單片結構,我在類的范圍內制作了所有GUI,並且我創建了一個處理連接和數據檢索的對象。
為了處理池化時間的需要,我使用了System.Timers.Timer
,它基本上是一個帶有觸發定時事件的Thread包裝,在這里我執行了數據池。
當找到新數據時,我需要從定時器觸發的函數(根據定義在其他線程中)觸發屬於GUI(現在在主線程中運行)的X類中的方法。
我第一次嘗試將方法直接調用到由計時器觸發的方法時,導致交叉線程錯誤:因為該方法駐留在X類中並且未在計時器線程中構造。
然后我再次嘗試使用其他方法。 我在類中創建了一個事件,用於讀取數據並將GUI對象訂閱到該事件。
現在,當我觸發事件.net產生一個異常,說我發送者對象實例為空,完全不知道為什么,但我懷疑這是因為對象本身它是用主線程中的GUI對象創建的,當我決定從另一個線程發送對象(它正在生成事件),實例根本不存在,因為沒有在那里創建。
這是計時器到期時調用的函數:
private void PoolearMensajes(object Sender, ElapsedEventArgs e)
{
try
{
pRdr.getPendingMessages(); <--- This function creates the exception
if (pRdr.MensajesPendientes > 0)
{
this.oSysIcon.Text = pRdr.MensajesPendientes.ToString() + " tickets pendientes";
this.oSysIcon.BalloonTipIcon = ToolTipIcon.Info;
this.oSysIcon.BalloonTipText = pRdr.MensajesPendientes.ToString() + " tickets pendientes";
this.oSysIcon.BalloonTipTitle = "Información";
this.oSysIcon.ShowBalloonTip(3000);
System.Media.SystemSounds.Exclamation.Play();
}
}
catch (Exception ex)
{
this.oSysIcon.BalloonTipTitle = "Error";
this.oSysIcon.Text = "Ha ocurrido un error.";
this.oSysIcon.BalloonTipIcon = ToolTipIcon.Error;
this.oSysIcon.BalloonTipText = ex.Message;
this.oSysIcon.ShowBalloonTip(3000);
System.Media.SystemSounds.Exclamation.Play();
}
}
以下是該方法駐留在主線程中創建的數據檢索器對象中:
public delegate void TicketsFoundHandler(object sender, TicketEventArgs ta);
public event TicketsFoundHandler TicketsFound;
public void getPendingMessages()
{
string sSQL;
sSQL = " an SQL Query that counts rows;";
oCmd = new SqlCommand(sSQL, oConn);
oConn.Open();
this.i_pendmsg = (int)oCmd.ExecuteScalar();
if (this.i_pendmsg > 0)
{
TicketEventArgs ta = new TicketEventArgs("", this.i_pendmsg);
TicketsFound(this, ta); <---- ERROR!
}
oConn.Close();
}
它的錯誤消息: Object reference not set to an instance of an object
。
任何想法,任何改進,或者我沒有考慮過的東西?
我第一次嘗試將方法直接調用到由計時器觸發的方法時,導致交叉線程錯誤:因為該方法駐留在X類中並且未在計時器線程中構造。
你快到了。 您只需要調用BeginInvoke()
來調用GUI線程上的操作。
您可能還會發現使用BackgroundWorker
更加容易。
編輯:
你問題中的具體錯誤是因為沒有訂閱你的TicketsFound
事件。 使用TicketsFound += ...
來執行此操作。 另外,在引發事件之前檢查null:
if (TicketsFound != null) TicketsFound(...)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.