从后台线程在UI线程上打开一个窗体
我想从后台线程(我认为)打开窗体,因为当我调用formName.Show();被冻结的形式(不是主要形式)。从后台线程在UI线程上打开一个窗体
目标:
当用户接收到新的消息时,弹出一个newMessageFrm具有用于答复的新的消息。
问题:
新形式的锁。
这里是我使用的代码:
static void OnNewMessage(object sender, S22.Xmpp.Im.MessageEventArgs e)
{
if(CheckIfFormIsOpen(e.Jid.ToString(), e.Message.ToString()) == true){
} else
{
newMessageFrm tempMsg = new newMessageFrm(e.Jid.ToString());
tempMsg._msgText = e.Jid.ToString() + ": " + e.Message.ToString();
tempMsg.frmId = e.Jid.ToString();
tempMsg.Show(); //This locks up the application
}
}
我使用Visual Studio 2015年,C#和S22.Xmpp(正如你可以从代码中看到。)
当此事件触发时,表单弹出,但随后锁定。
如果您需要更多信息,请让我知道。
不幸的是,我不知道如何做到这一点,没有任何现有的形式。但我相信你有一些你可以访问的主要形式。或者你也可以使用
var invokingForm = Application.OpenForms[0];
所以,你可以改变你的方法的代码这样获得Form
:
static void OnNewMessage(object sender, S22.Xmpp.Im.MessageEventArgs e)
{
var invokingForm = Application.OpenForms[0]; // or whatever Form you can access
if (invokingForm.InvokeRequired)
{
invokingForm.BeginInvoke(new EventHandler<S22.Xmpp.Im.MessageEventArgs>(OnNewMessage), sender, e);
return; // important!!!
}
// the rest of your code goes here, now running
// on the same ui thread as invokingForm
if(CheckIfFormIsOpen(e.Jid.ToString(), e.Message.ToString()) == true)
{
}
else
{
newMessageFrm tempMsg = new newMessageFrm(e.Jid.ToString());
tempMsg._msgText = e.Jid.ToString() + ": " + e.Message.ToString();
tempMsg.frmId = e.Jid.ToString();
tempMsg.Show();
}
}
请注意,我说assumend是S22.Xmpp.Im.MessageEventArgs
从System.EventArgs
继承。
谢谢,这种方法正在工作! –
在WinForms中,仍然需要UI对象需要位于具有消息泵的线程上。这通常是主应用程序线程,也称为UI线程。
在Winforms检查是否在正确的线程访问UI对象是用Control.InvokeRequired
完成。如果这返回true,则表示您没有在适当的线程上,并且需要使用Invoke操作。
既然你知道你是一个不同的线程,你不需要检查,你可以只是调用。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(BadBackgroundLaunch);
ThreadPool.QueueUserWorkItem(GoodBackgroundLaunch);
}
private void GoodBackgroundLaunch(object state)
{
this.Invoke((Action) (() =>
{
var form2 = new SecondForm();
form2.Text = "Good One";
form2.Show();
}));
}
private void BadBackgroundLaunch(object state)
{
var form2 = new SecondForm();
form2.Text = "Bad one";
form2.Show();
}
}
你怎么知道OP的方法是在'Form'类中声明的?他只表明这是一种_static_方法。所以你忽略了哪个'Control',他应该调用'Invoke'。 –
应用程序中的任何'Control'都可以。他们都应该在UI线程上。你的方法'Application.OpenForms [0]'很好。 – bigtlb
是的,这就是为什么我认为找到控件是问题的一部分。 –
从主(UI)线程打开窗体。 –
使用您可访问的任何控件/表单的Invoke或BeginInvoke。看看这个:http://*.com/questions/6708765/how-to-invoke-when-i-have-no-control-available – Gusman
PLease不回答问题中的意见。经过一段时间的评论被删除后,用户也无法将评论标记为答案 – Stralos