从另一个窗体更新对话框 [英] Updating a dialog from another form
问题描述
您可以使用此方法在
应用程序中显示模态对话框。当调用此方法时,它后面的代码不会执行
,直到对话框关闭后
我想要什么,特别是因为这意味着对话更新只会在再次关闭之后发生。
我在这里做错什么?这似乎是一个微不足道的问题,但解决方案逃避了我。请记住,我是C#GUI编程的新手。
此外,我想问一下使用Invoke()的正确的地方?在调用对话方法或者对话框更新方法本身的时候,你会以主窗体的形式使用它吗?
看起来你在这里使用多个线程,所以调用的东西不是必需的。调用只需要进行跨线程调用 - 您正在创建多个表单,但所有代码都以相同的线程运行。
如果您正在开展工作主要的UI线程(由代码在按钮点击事件中暗示),然后定期调用 Application.DoEvents()
以允许进度表单刷新。 p>
更好的解决方案是使用 BackgroundWorker
,并定期报告其进度。
然后,您可以在BackgroundWorker的 ProgressChanged
事件中更新进度表单(将在主线程中执行,因此您仍然无需调用任何内容)。 p>
I know there are a lot of similar questions out there and I have read through a lot of them. Unfortunately, I still couldn't solve my problem after reading through them - however I am relatively new to C#. According to docs the problem of not being thread safe results in an InvalidOperationException
when using the debugger. This is not the case in my problem.
I've recreated the problem with a simple raw test class to concentrate on my problem.
The main form is supposed to show a kind of a progress dialog.
public partial class ImportStatusDialog : Form
{
public ImportStatusDialog()
{
InitializeComponent();
}
public void updateFileStatus(string path)
{
t_filename.Text = path;
}
public void updatePrintStatus()
{
t_printed.Text = "sent to printer";
}
public void updateImportStatus(string clientName)
{
t_client.Text = clientName;
}
public void updateArchiveStatus()
{
t_archived.Text = "archived";
}
}
When that code is called without any Invoke() from the main form:
private void button1_Click(object sender, EventArgs e)
{
ImportStatusDialog nDialog = new ImportStatusDialog();
nDialog.Show();
nDialog.updateFileStatus("test");
Thread.Sleep(1000);
nDialog.updateImportStatus("TestClient");
Thread.Sleep(1000);
nDialog.updatePrintStatus();
Thread.Sleep(1000);
nDialog.updateArchiveStatus();
Thread.Sleep(1000);
nDialog.Close();
}
And even when I call it like this:
private void button3_Click(object sender, EventArgs e)
{
ImportStatusDialog nDialog = new ImportStatusDialog();
nDialog.Show();
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
nDialog.updateFileStatus("Test");
});
}
else
{
nDialog.updateFileStatus("Test");
}
Thread.Sleep(1000);
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
nDialog.updatePrintStatus();
});
}
else
{
nDialog.updatePrintStatus();
}
Thread.Sleep(1000);
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
nDialog.updateImportStatus("cName");
});
}
else
{
nDialog.updateImportStatus("cName");
}
Thread.Sleep(1000);
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
nDialog.updateArchiveStatus();
});
}
else
{
nDialog.updateArchiveStatus();
}
Thread.Sleep(1000);
nDialog.Close();
}
the dialog which looks like this in the designer (in my example)
will be displayed like that:
When I use ShowDialog() instead of Show() the dialog displays correnctly, but as the API Doc points out
You can use this method to display a modal dialog box in your application. When this method is called, the code following it is not executed until after the dialog box is closed
which is not what I want, especially as it would mean that the dialog updating would only happen after it has been closed again.
What am I doing wrong here? This seems to be a trivial problem and yet the solution evades me. Please keep in mind that I am new to C# GUI programming.
Also, I would like to ask what would be the right place for using the Invoke()? Do Would you use it in the main form when calling the dialog methods or rather in the dialog update methods itself?
It doesn't look like you're using multiple threads here, so the invoke stuff is not required. Invoke is only needed for cross-thread calls - you are creating multiple forms, but all your code is running in the same thread.
If you're doing your work in the main UI thread (as implied by the code being in a button click event), then just call Application.DoEvents()
periodically to allow the progress form to refresh.
A better solution would be to use a BackgroundWorker
for your work, and have it report its progress periodically.
Then you can update the progress form in the BackgroundWorker's ProgressChanged
event (which will be executed in the main thread, so you still don't have to invoke anything).
这篇关于从另一个窗体更新对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!