2013-01-15 38 views
1

我有一个WPF窗口,带有一个产生BackgroundWorker线程来创建和发送电子邮件的按钮。在此BackgroundWorker运行时,我想显示一个用户控件,显示一些消息,后面跟着一个动画“...”。该动画由用户控件中的计时器运行。当backgroundworker运行时计时器没有被调用

即使我的邮件发送代码位于BackgroundWorker上,用户控件中的计时器也永远不会被调用(当然,只有当Backgroundworker完成时,它才会失败)。

相关的代码在WPF窗口:

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

任何想法,为什么它锁定了:

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”)相关的代码?

+0

您是否必须在UI线程上调用'worker_DoWork',因为我没有看到在那里调用的任何UIElements,也许删除'worker_DoWork'中的Dispatcher.Invoke将解决该问题。或将其更改为'Dispatcher.BeginInvoke' –

+0

哎呀我砍了一些访问UI的代码。现在重新添加。 – akevan

回答

2

在您的worker_DoWork方法中使用Dispatcher.Invoke将执行回到UI线程,因此您不是异步执行该工作。

根据您显示的代码,您应该可以将其删除。

如果在完成工作后需要显示结果值,请将其放入DoWorkEventArgs,并且您将能够在worker_RunWorkerCompleted处理程序的事件参数中访问它(在UI线程上)。

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

+0

对不起,我忘了在上面包含一些UI访问代码。这就是为什么它使用Dispatcher.Invoke。我重新添加了它。 – akevan

+0

但是你指出了这个问题 - “在你的worker_DoWork方法中使用Dispatcher.Invoke正在执行回UI界面线程”。我需要获取UI线程上的UI元素,然后将它们作为参数传递给BG工作者,从BG工作者中移除该Dispatcher,然后所有工作都很好。谢谢!! – akevan

相关问题