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

Chi*_*han 9 c# wpf multithreading messagebox backgroundworker

在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");                
    }   
}
Run Code Online (Sandbox Code Playgroud)

但是这个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");
}
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 10

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

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

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


Sco*_*ain 9

代替

MessageBox.Show("I should block the main window"); 
Run Code Online (Sandbox Code Playgroud)

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

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


Ste*_*ary 6

呼叫ReportProgress并传递thisMessageBox.Show.