如何在多线程应用程序中安全地显示消息框? [英] How to safely show messagebox in multi-thread application?

查看:50
本文介绍了如何在多线程应用程序中安全地显示消息框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些事情要做背景,如果发生错误,我想显示一个消息框.首先我试过

var _timer = new System.Threading.Timer((o) =>{if(!DoCheck()){Messagebox.Show("消息");}});

没有发生任何错误.

我还有另一项工作要在后台完成,它是通过按钮点击调用的,比如

private void button3_Click(object sender, EventArgs e){var task = new Task(() =>{做工作();Messagebox.Show("完成");});_task.Start();}

显示 MessageBox 时抛出 System.Reflection.TargetInvocationException.

我也尝试过 this.Invoke,它也引发了异常.我的问题是:

  1. 第一种情况安全吗?
  2. 如何使第二种情况奏效?

解决方案

  1. 没有.您最好在 WinForms 应用程序中使用 System.Windows.Forms.Timer.文档专门称此出:

<块引用>

此 Windows 计时器专为使用 UI 线程执行处理的单线程环境而设计.它要求用户代码具有可用的 UI 消息泵,并且始终在同一线程中操作,或者将调用编组到另一个线程上.

此外,这取决于您的 DoCheck 方法在做什么.我们需要查看该方法的代码.

  1. 使用 BeginInvoke 方法:

    var form = this;var task = new Task(() =>{做工作();form.BeginInvoke(() =>{MessageBox.Show("完成");});});

I have something doing background and I want to show a messagebox if something wrong happens. First I tried

var _timer = new System.Threading.Timer((o) =>
{
    if(!DoCheck()){
        Messagebox.Show("The message");
    }
});

Nothing wrong happens.

And I have another job to be done in background, and it's invoked by button click, like

private void button3_Click(object sender, EventArgs e)
{
    var task = new Task(() =>
    {
        DoWork();
        Messagebox.Show("Done");
    });
    _task.Start();
}

A System.Reflection.TargetInvocationException is thrown when the MessageBox is shown.

I have also tried this.Invoke, it raised an exception, too. My question is:

  1. Is the first case safe?
  2. How to make the second case work?

解决方案

  1. No. You should preferably be using System.Windows.Forms.Timer in a WinForms application. The documentation specifically calls this out:

This Windows timer is designed for a single-threaded environment where UI threads are used to perform processing. It requires that the user code have a UI message pump available and always operate from the same thread, or marshal the call onto another thread.

Furthermore, it depends on what your DoCheck method is doing. We will need to see the code of that method.

  1. Use the BeginInvoke method:

    var form = this;
    var task = new Task(() =>
    {
        DoWork();
        form.BeginInvoke(() => 
        {
            MessageBox.Show("Done");
        });
    });
    

这篇关于如何在多线程应用程序中安全地显示消息框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆