簡體   English   中英

嘗試在線程之間傳遞事件的問題

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM