我有一个带有2个表单的WinForms客户端。第一种形式调用一个单独的类,该类使用'SignalR'来接收来自WebApi的通知。该类中特定消息的集线器代理的设置是:
onResult = myProxy.On<int>("Result", (id) =>
{
Result?.Invoke(this, new ResultEventArgs(id));
});
在第一种形式中,我订阅了Result
事件,然后我拥有:
private void OnResult(object sender, ResultEventArgs e)
{
using (var form = new SecondForm(e))
{
var dialogResult = form.ShowDialog(this);
if (dialogResult == DialogResult.Cancel)
return;
}
}
我在CrossThreadException
上得到一个var dialogResult = form.ShowDialog(this);
,第一个表单(this
)在UI线程上打开。第二种形式是在SignalR
类使用的同一线程中打开的。
我确实需要使用ShowDialog(this)
打开第二个表单,因为它需要成为应用程序中最顶层的表单。
是否有解决此问题的方法?是否可以在UI线程中打开第二个表单?
更新:
一种可行的解决方法:
form.TopMost = true;
form.StartPosition = FormStartPosition.CenterScreen;
唯一的缺点是该表单是桌面上最顶层的表单,而不仅是在应用程序中。
答案 0 :(得分:2)
您不能在单个UI线程以外的任何线程上创建,更改或访问任何UI控件。您必须在现有控件上调用.Invoke(...)
,以将来自另一个线程的调用编组回UI。
尝试一下:
private void OnResult(object sender, ResultEventArgs e)
{
Action x = () =>
{
using (var form = new SecondForm(e))
{
var dialogResult = form.ShowDialog(this);
if (dialogResult == DialogResult.Cancel)
return;
}
};
this.Invoke(x);
}