更新 GUI 时冻结

用户9940552

我有一个带有标题、标签和确定按钮的警告框。每当它应该弹出时,它应该重新使用同一个窗口,而不是打开一个新窗口。

我从外部线程收到一个对话框事件。它可以接收已知程序之外的消息。Show()每次收到消息时我都想打电话

在此处输入图片说明

public partial class AlertBox : Form
{
    private static AlertBox instance;
    public static AlertBox Instance => instance ?? (instance = new AlertBox());

    private AlertBox()
    {
        InitializeComponent();
    }

    private void AlertBox_Load(object sender, EventArgs e)
    {
        MessageLabel.Text = "";
        Text = "";
    }

    public void Show(string text, string title)
    {
        Show();
        BringToFront();
        Text = title;
        MessageLabel.Text = text;
    }

    private void OkButton_Click(object sender, EventArgs e)
    {
        MessageLabel.Text = "";
        Text = "";
        Hide();
    }
}

但是,Show(text, title)如图所示调用时

internal class Driver
{
    private readonly AlertBox _alertBox = AlertBox.Instance;
    public void Initialize()
    {
        // Receive dialog event.
        _connection.OnDialogReceived += (text, title) =>
        {
            _alertBox.Show(text, title);
        };
    }
}

警报框出现,设置窗口标题,然后冻结。请注意,该按钮已变得不可见。

在此处输入图片说明

我曾尝试使用Invoke. 它冻结,结果完全相同。

    public void ShowWithInvoke(string text, string title)
    {
        if (!Created)
        {
            CreateControl();
        }

        if (!IsHandleCreated)
        {
            CreateHandle();
        }

        Invoke((MethodInvoker)delegate
        {
            Show();
            BringToFront();
            Text = title;
        });

        if (!MessageLabel.Created || !MessageLabel.IsHandleCreated)
        {
            MessageLabel.CreateControl();
        }

        MessageLabel.Invoke((MethodInvoker)delegate
        {
            MessageLabel.Text = text;
        });
    }
神秘性

解决此问题的常用方法是将发送警报的代码与显示警报的代码分离。

首先,您应该创建一个类,该类的唯一目的是将更新传递给正在侦听的任何 UI。

public class MessageUpdater
{
    public event EventHandler<string> MessageSent;
    public void SendMessage(string message)
    {
        this.MessageSent?.Invoke(this, message);
    }
}

这很简单。它只接受消息,如果有附加到事件的处理程序,它就会引发事件。

现在,您AlertBox只需接受一个MessageUpdater实例并在触发事件Label更新它MessageSent

public partial class AlertBox : Form
{
    public AlertBox()
    {
        InitializeComponent();
    }

    private MessageUpdater _messageUpdater = null;

    public MessageUpdater MessageUpdater
    {
        set
        {
            if (_messageUpdater != null)
            {
                _messageUpdater.MessageSent -= UpdateMessage;
            }
            if (value != null)
            {
                _messageUpdater = value;
                _messageUpdater.MessageSent += UpdateMessage;
            }
        }
    }

    private void UpdateMessage(object sender, string message)
    {
        if (this.InvokeRequired)
        {
            this.Invoke((Action)(() => this.UpdateMessage(sender, message)));
        }
        else
        {
            this.MessageLabel.Text = message;
        }
    }
}

这里有两个棘手的部分是处理新的附件MessageUpdater(以及删除现有的附件),然后在需要时将调用编组到 UI 线程。

我创建的用于测试的代码相当简单。

        var mu = new MessageUpdater();

        var counter = 0;
        var timer = new System.Threading.Timer((System.Threading.TimerCallback)(x =>
        {
            mu.SendMessage((counter++).ToString());
        }), null, TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0));

        var ab = new AlertBox();
        ab.MessageUpdater = mu;
        ab.ShowDialog();

这里棘手的部分是System.Threading.Timer我曾经MessageUpdater 在非 UI 线程上将消息推送到以便.ShowDialog不会冻结。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

尝试更新按钮标签文本时,Python GUI冻结或关闭

来自分类Dev

通过计时器更新标签时,C#GUI冻结

来自分类Dev

Pyqt Gui在循环时冻结

来自分类Dev

使用线程时 Gui 冻结

来自分类Dev

更新 ObservableCollection 时 UI 冻结

来自分类Dev

使用waitForFinished时,Qt GUI冻结。

来自分类Dev

使用多重处理时,Tkinter GUI冻结。

来自分类Dev

使用异步/等待时,GUI冻结

来自分类Dev

调用方法时Java Swing GUI冻结

来自分类Dev

执行循环时JavaFX GUI保持冻结

来自分类Dev

单击 jButton 时 Java GUI 冻结

来自分类Dev

使用多线程时 GUI 仍然冻结

来自分类Dev

使用回调时更新GUI句柄

来自分类Dev

SwiftUI列表在@ObservedObject更新时冻结

来自分类Dev

iOS 8在更新UserDefaults对象时冻结

来自分类Dev

Xcode 8.1在Pod安装/更新时冻结

来自分类Dev

机器在更新 secureboot-db 时冻结

来自分类Dev

在QApplication上使用Windows :: SetParent时,GUI冻结

来自分类Dev

通过IronPython创建的Gui表单在处理时冻结

来自分类Dev

运行方法时 Tkinter GUI 冻结(如何添加线程?)

来自分类Dev

Tkinter GUI冻结

来自分类Dev

PySide / Python GUI冻结

来自分类Dev

AFNetworking冻结我的GUI

来自分类Dev

Qt-GUI冻结

来自分类Dev

任务冻结了GUI

来自分类Dev

多个Linux GUI冻结

来自分类Dev

Swing GUI 冻结

来自分类Dev

tkinter 避免 GUI 冻结

来自分类Dev

WxPython - GUI 冻结