C#类库在单独的线程上显示和更新窗体

本文关键字:显示 更新 窗体 线程 类库 单独 | 更新日期: 2023-09-27 18:20:11

我正在用一个公共方法在C#中创建一个dll,该方法应该从另一个程序中调用。当该程序调用这种方法:"ShowMsg"时,它应该创建并显示一个小表单(基本上是一个警报弹出窗口),其中根据消息的类型以特定的颜色显示特定的消息。在调用程序使用不同的参数再次调用ShowMsg之前,该表单应保持可见,同一表单应根据这些参数更新其消息和颜色。

我现在在呼叫程序中有这样的:

//Create the form here but do not show it yet
AlertMsg alertMsg = new AlertMsg();
//Show the form with this message
alertMsg.ShowMsg("message 1", "message 1 description", AlertMsg.MsgTypes.Warning );
//do lengthy stuff, simulated with a sleep here
System.Threading.Thread.Sleep(4000);
//Update the form showing this message
alertMsg.ShowMsg("message 2", "message 2 description", AlertMsg.MsgTypes.Critical);
//do lengthy stuff, simulated with a sleep here
System.Threading.Thread.Sleep(4000);

我已经从"AlertMsg"创建了,看起来应该是这样。它还显示我第一次打电话时的表格。ShowMsg。只有表格上的标签保持白色。此外,当我下次调用.ShowMsg时,它不会更新表单。

我认为要解决这个问题,我应该在一个单独的线程上创建表单,但我不太知道如何做到这一点。有人能给我指正确的方向吗?

非常感谢。


我尝试了我得到的刷新提示,现在我有了这个。以上仍然是调用程序,这一点保持不变。

现在,在我的类AlertMsg中,我有这样的内容(为了简洁起见,省略了一些代码):

public class AlertMsg
{
    frmAlertMsg _frmAlertMsg;
    public AlertMsg()
    {
        _frmAlertMsg = new frmAlertMsg();
    }
    public void Show(string header, string text, MsgTypes msgType)
    {
        _frmAlertMsg.showMsg(header, text, msgType);  
    }
}

在形式课上,我有这个:

private void frmAlertMsg_Load(object sender, EventArgs e)
{
    this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Right - 420, Screen.PrimaryScreen.WorkingArea.Bottom - 120);
}
internal void showMsg(string header, string text, AlertMsg.MsgTypes typeM )
{
    //left out setting the colors part here
    lblHeader.Text = header;
    lblDescription.Text = text;
    this.Show();
    this.Refresh();    
}

现在,它完美地显示了表单,并为我提供的文本设置了标签。当我稍后再次调用showMsg时,它也会更新。

再次感谢您。

C#类库在单独的线程上显示和更新窗体

您不应该在另一个线程中创建表单,不应该。您的应用程序应该有一个UI线程,而不是几个。如果您有非UI工作,您应该将该工作卸载到非UI线程。创建多个UI线程是一件非常痛苦的事情,如果可能的话,你应该避免这样做。当你在UI线程中做非UI工作时,创建一个新的线程来做UI工作会给你自己带来比你需要的更多的工作。

相反,您需要异步编写程序。您不需要长时间阻塞UI线程并让它发送消息。

AlertMsg alertMsg = new AlertMsg();
alertMsg.ShowMsg("message 1", "message 1 description", 
    AlertMsg.MsgTypes.Warning);
await Task.Run(() => SomeLongRunningOperation());
alertMsg.ShowMsg("message 2", "message 2 description", 
    AlertMsg.MsgTypes.Critical);
await Task.Run(() => AnotherLongRunningOperation());

简单的解决方案是在表单上绘制后使用Application.DoEvents()。然而,将长期运行的任务放到一个单独的线程中绝对是正确的选择。

线程示例:

//Create the form here but do not show it yet
AlertMsg alertMsg = new AlertMsg();
//Show the form with this message
alertMsg.ShowMsg("message 1", "message 1 description", AlertMsg.MsgTypes.Warning );
ThreadStart ts = new ThreadStart(() =>
            {
                //do lengthy stuff, simulated with a sleep here
                System.Threading.Thread.Sleep(4000);
                if (alertMsg.InvokeRequired)
                {
                    this.Invoke(new Action(() => alertMsg.Hide()));
                }
            });
Thread th = new Thread(ts);
th.Name = "longrunningtast";
th.Start();

如果必须从新线程写入表单,请不要忘记使用Invoke()。