0

这是一个 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 主题中的 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;
        }
}
4

1 回答 1

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() 事件。

于 2013-05-18T03:48:21.437 回答