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时,它也会更新。
再次感谢您。
您不应该在另一个线程中创建表单,不应该。您的应用程序应该有一个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()。