当backgroundworker运行时,计时器不会被调用

时间:2013-01-15 21:18:39

标签: wpf multithreading user-interface timer backgroundworker

我有一个带有按钮的WPF窗口,该按钮产生BackgroundWorker线程以创建和发送电子邮件。当这个BackgroundWorker运行时,我想显示一个用户控件,显示一些消息后跟一个动画“...”。该动画由用户控件内的计时器运行。

即使我的邮件发送代码在BackgroundWorker上,用户控件中的计时器也永远不会被调用(好吧,只有当Backgroundworker完成时才会被调用,这有点辜负了目的......)。

WPF窗口中的相关代码:

private void button_Send_Click(object sender, RoutedEventArgs e)
{
    busyLabel.Show(); // this should start the animation timer inside the user control

    BackgroundWorker worker = new BackgroundWorker();
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.RunWorkerAsync();      
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    this.Dispatcher.Invoke((Action)(() =>
    {      
        string body = textBox_Details.Text;
        body += "User-added addtional information:" + textBox_AdditionalInfo.Text; 

        var smtp = new SmtpClient
        {
            ...
        };

        using (var message = new MailMessage(fromAddress, toAddress)
        {
            Subject = subject,
            Body = body
        })
        {
            smtp.Send(message);
        }
    }));

}

用户控件中的相关代码(“BusyLabel”):

public void Show()
{
    tb_Message.Text = Message;
    mTimer = new System.Timers.Timer();
    mTimer.Interval = Interval;
    mTimer.Elapsed += new ElapsedEventHandler(mTimer_Elapsed);
    mTimer.Start();
}

void mTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    this.Dispatcher.Invoke((Action)(() =>
    { 

        int numPeriods = tb_Message.Text.Count(f => f == '.');
        if (numPeriods >= NumPeriods)
        {
            tb_Message.Text = Message;
        }
        else
        {
            tb_Message.Text += '.';
        }         
    }));
}

public void Hide()
{
    mTimer.Stop();
}

任何想法为何锁定?

1 个答案:

答案 0 :(得分:2)

Dispatcher.Invoke方法中使用worker_DoWork会将执行重新放回UI线程上,因此您实际上并不是异步执行工作。

您应该可以根据您显示的代码删除它。

如果在工作完成后需要显示结果值,请将其放在DoWorkEventArgs中,然后您就可以在worker_RunWorkerCompleted处理程序中访问它(在UI线程上)事件args。

使用BackgroundWorker的主要原因是编组是在封面下处理的,因此您不必使用Dispatcher.Invoke