从BackGroundWorker向消息对话框发送消息时发生NullReferenceException

时间:2013-05-18 03:34:36

标签: c# multithreading winforms nullreferenceexception

这是一个C#winform .Net framework 2.0项目:耗时的网络传输作业在BackupgroundWorker中运行。在此后台工作线程中,SynchronizationContext方法用于将当前作业标题发送到主UI线程中的消息对话框。但是,在我的代码中,线程竞争问题发生并且有时会给出“NullReferenceException”(并非总是,而是随机)。这是我的代码:

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
 }

在后台工作线程中:

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
}

问题是:有时候,后台工作线程中的“RestoreMsgForm.synContext.Send()”将在UI thead中的m_msgForm.ShowDialog()之前运行。 在这种情况下,将抛出NullReferenceException。

如何解决这个问题?谢谢。

RestoreMsgForm的定义是

  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;
        }
}

1 个答案:

答案 0 :(得分:1)

看看它是否像这样:

    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);
        }
    }

*请注意,我们必须为BackgroundWorker()设置.WorkerReportsProgress = true,以便我们可以使用ReportProgress()并接收ProgressChanged()事件。