简体   繁体   中英

NullReferenceException happens when sending message back to message dialog from BackGroundWorker

It's a C# winform .Net framework 2.0 project: The time-consuming network transferring jobs run in a BackupgroundWorker. In this backgroundwork thread, SynchronizationContext method is used to send the current job title to a message dialog in the main UI thread. However, in my code, thread racing problem happens and "NullReferenceException" is given sometime (not always, but randomly). Here is my code:

private void DoBtn_Click(object sender, EventArgs e)
{
    m_msgForm = new MsgForm();       //m_msgForm is a member variable of the class, and MsgForm is a form class with a "public static SynchronizationContext synContext"
    m_msgForm.UpdateMsg("starting ...");   //UpdateMsg is public method to show progress information

BackgroundWorker myBackgroundWorker = new BackgroundWorker();
        myBackgroundWorker.DoWork +=new DoWorkEventHandler(myBackgroundWorker_DoWork);
        myBackgroundWorker.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(myBackgroundWorker_RunWorkerCompleted);
        myBackgroundWorker.RunWorkerAsync(theBackgroundArgument);  

    m_msgForm.ShowDialog();    //show as a modal dialog
 }

And in the Background worker thread:

private void myBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
   //... some code
   string msgText ="doing job: " +job.Title;
   RestoreMsgForm.synContext.Send(m_msgForm.UpdateMsg, msgText);    //send message to m_msgForm in the UI thread 

   //... some code
}

The problem is : sometime the "RestoreMsgForm.synContext.Send() in the backgroundworker thread will run before m_msgForm.ShowDialog() in the UI thead. And in this case, NullReferenceException will be throw.

How to solve this problem? thanks.

the definition of RestoreMsgForm is

  public partial class RestoreMsgForm : Form
    {
        public static SynchronizationContext synContext;
        public RestoreMsgForm()
        {
            InitializeComponent();
        }
        private void RestoreMsgForm_Load(object sender, EventArgs e)
        {
            synContext = SynchronizationContext.Current;
        }
        public void UpdateMsg(object msg)
        {
            msgLabel.Text = (string)msg;
        }
}

See if it works like this instead:

    private void DoBtn_Click(object sender, EventArgs e)
    {
        m_msgForm = new MsgForm();       //m_msgForm is a member variable of the class, and MsgForm is a form class with a "public static SynchronizationContext synContext"
        m_msgForm.UpdateMsg("starting ...");   //UpdateMsg is public method to show progress information

        BackgroundWorker myBackgroundWorker = new BackgroundWorker();
        myBackgroundWorker.DoWork += new DoWorkEventHandler(myBackgroundWorker_DoWork);
        myBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(myBackgroundWorker_RunWorkerCompleted);

        myBackgroundWorker.WorkerReportsProgress = true;
        myBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(myBackgroundWorker_ProgressChanged);

        myBackgroundWorker.RunWorkerAsync(theBackgroundArgument);  
    }

    private void myBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = (BackgroundWorker)sender;
        worker.ReportProgress(-1);

        //... some code

        string msgText = "doing job: " + job.Title;
        worker.ReportProgress(0, msgText);

        //... some code

        worker.ReportProgress(0, "...other text...");

        //... some code

        worker.ReportProgress(0, "...etc...");
    }

    void myBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (e.ProgressPercentage == -1)
        {
            m_msgForm.ShowDialog();    //show as a modal dialog
        }
        else
        {
            m_msgForm.UpdateMsg(e.UserState.ToString);
        }
    }

*Note that we have to set .WorkerReportsProgress = true for the BackgroundWorker() so we can use ReportProgress() and receive the ProgressChanged() event.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM