使用WPF中的Backgroundworker为主应用程序弹出MessageBox

时间:2010-06-23 19:02:54

标签: c# wpf multithreading backgroundworker messagebox

在WPF应用程序中,我使用BackgroundWorker定期检查服务器上的条件。虽然这样可以正常工作,但是如果在检查过程中出现问题,我想弹出一个MessageBox来通知用户。

这就是我所拥有的:

public static void StartWorker()
{
    worker = new BackgroundWorker();

    worker.DoWork += DoSomeWork;
    worker.RunWorkerAsync();
}

private static void DoSomeWork(object sender, DoWorkEventArgs e)
{
    while (!worker.CancellationPending)
    {
        Thread.Sleep(5000);

        var isOkay = CheckCondition();

        if(!isOkay)
           MessageBox.Show("I should block the main window");                
    }   
}

但是这个MessageBox不会阻止主窗口。我仍然可以点击我的WPF应用程序并使用MessageBox更改我喜欢的任何内容。

我该如何解决这个问题?谢谢,


编辑:

作为参考,这就是我最终做的事情:

public static void StartWorker()
{
    worker = new BackgroundWorker();

    worker.DoWork += DoSomeWork;
    worker.ProgressChanged += ShowWarning;
    worker.RunWorkerAsync();
}

private static void DoSomeWork(object sender, DoWorkEventArgs e)
{
    while (!worker.CancellationPending)
    {
        Thread.Sleep(5000);

        var isOkay = CheckCondition();

        if(!isOkay)
           worker.ReportProgress(1);                
    }   
}

private static void ShowWarning(object sender, ProgressChangedEventArgs e)
{
    MessageBox.Show("I block the main window");
}

5 个答案:

答案 0 :(得分:10)

它不仅不会阻挡主窗口,它也很可能在它后面消失。这是它在不同线程上运行的直接结果。如果没有为消息框指定所有者,那么它将使用GetActiveWindow()API函数寻找一个所有者。它只考虑使用相同消息队列的窗口。这是一个特定于线程的属性。当然,丢失消息框很难处理。

同样,MessageBox仅禁用属于同一消息队列的窗口。因此不会阻止主线程创建的窗口。

通过让UI线程显示消息框来解决您的问题。使用Dispatcher.Invoke或利用ReportProgress或RunWorkerCompleted事件。听起来不适合这里的事件。

答案 1 :(得分:6)

致电ReportProgress并将this传递给MessageBox.Show

答案 2 :(得分:3)

替换

MessageBox.Show("I should block the main window"); 

this.Invoke((Func<DialogResult>)(() => MessageBox.Show("I should block the main window")));

这将导致消息框位于主线程上,并将阻止对UI的所有访问,直到获得响应。作为额外的奖励this.Invoke将返回一个可以投射到DialogResult的对象。

答案 3 :(得分:2)

正如Stephen和Hans所说,使用ReportProgress事件,并将数据传递给UI线程。如果您想要对MessageBox执行任何操作(对于isntance,更新控件),这一点尤为重要,因为后台线程无法直接执行此操作。你会得到一个跨线程的例外。

所以无论你需要做什么(更新进度条,将消息记录到UI等),都要将数据传递给UI线程,告诉UI线程需要做什么,但让UI线程去做。

答案 4 :(得分:1)

我像这样修改它并且对我很好

 return Application.Current.Dispatcher.Invoke(() => MessageBox.Show(messageBoxText, caption, button, icon));