[英]C# calling form.show() from another thread
如果我从另一个线程在 WinForms 对象上调用form.show()
,表单将抛出异常。 我可以通过什么方式向主应用程序线程添加新的可见表单? 否则,如何在不停止当前正在执行的线程的情况下打开表单?
这是我的示例代码。 我试图启动一个线程,然后在该线程中执行一些工作。 随着工作的进行,我将展示表格。
public void Main()
{
new Thread(new ThreadStart(showForm)).Start();
// Rest of main thread goes here...
}
public void showForm()
{
// Do some work here.
myForm form = new myForm();
form.Text = "my text";
form.Show();
// Do some more work here
}
尝试使用调用:
public static Form globalForm;
void Main()
{
globalForm = new Form();
globalForm.Show();
globalForm.Hide();
// Spawn threads here
}
void ThreadProc()
{
myForm form = new myForm();
globalForm.Invoke((MethodInvoker)delegate() {
form.Text = "my text";
form.Show();
});
}
“invoke”调用告诉表单“请在你的线程而不是我的线程中执行此代码”。 然后,您可以从委托中对 WinForms UI 进行更改。
有关 Invoke 的更多文档位于:http: //msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
编辑:您需要使用已经存在的 WinForms 对象才能调用调用。 我在这里展示了如何创建全局对象; 否则,如果您有任何其他 Windows 对象,它们也可以工作。
您应该在调用form.Show()
Application.Run()
之后调用 Application.Run() 。 例如:
public void showForm()
{
// Do some work here.
myForm form = new myForm();
form.Text = "my text";
form.Show();
Application.Run();
// Do some more work here
}
至于背后原因的详细信息, 这篇 msdn 帖子可能会有所帮助。
根据我的经验,最好的方法是:
var ac = (ReportPre)Application.OpenForms["ReportPre"];
Thread shower = new Thread(new ThreadStart(() =>
{
if (ac == null)
{
this.Invoke((MethodInvoker)delegate () {
ac = new ReportPre();
ac.Show();
});
}
else
{
this.Invoke((MethodInvoker)delegate
{
pictureBox1.Visible = true;
});
if (ac.InvokeRequired)
{
ac.Invoke(new MethodInvoker(delegate {
ac.Hide();
ac.Show();
}));
}
}
}));
shower.Start();
如果您的用例是在主 GUI 线程繁忙(如加载栏)时显示 GUI,您可以执行以下操作:
private void MethodWithLoadingBar()
{
Thread t1 = new Thread(ShowLoading);
t1.Start();
// Do the Main GUI Work Here
t1.Abort();
}
private void ShowLoading()
{
Thread.Sleep(1000); //Uncomment this if you want to delay the display
//(So Loading Bar only shows if the Method takes longer than 1 Second)
loadingGUI = new LoadingGUI();
loadingGUI.label1.Text = "Try to Connect...";
loadingGUI.ShowDialog();
}
我的 LoadingGUI 是一个带有公共标签和样式设置为 Marquee 的 ProgressBar 的简单表单
在网上搜索并没有找到好的解决方案后,我想出了自己的办法:
public async Task FunctionWhereIStartForm( Func<Delegate,object>invoke )
{
//this is on another thread
invoke( new MethodInvoker( ( ) =>
{
new formFoo().Show( );
} ) );
}
然后这样调用:
await FunctionWhereIStartForm(Invoke);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.