2016-01-06 78 views
-1

我想從後臺線程(我認爲)打開窗體,因爲當我調用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(正如你可以從代碼中看到。)

當此事件觸發時,表單彈出,但隨後鎖定。

如果您需要更多信息,請讓我知道。

+2

從主(UI)線程打開窗體。 –

+1

使用您可訪問的任何控件/表單的Invoke或BeginInvoke。看看這個:http://stackoverflow.com/questions/6708765/how-to-invoke-when-i-have-no-control-available – Gusman

+0

PLease不回答問題中的意見。經過一段時間的評論被刪除後,用戶也無法將評論標記爲答案 – Stralos

回答

1

不幸的是,我不知道如何做到這一點,沒有任何現有的形式。但我相信你有一些你可以訪問的主要形式。或者你也可以使用

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.MessageEventArgsSystem.EventArgs繼承。

+0

謝謝,這種方法正在工作! –

0

在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(); 
    } 
} 
+0

你怎麼知道OP的方法是在'Form'類中聲明的?他只表明這是一種_static_方法。所以你忽略了哪個'Control',他應該調用'Invoke'。 –

+0

應用程序中的任何'Control'都可以。他們都應該在UI線程上。你的方法'Application.OpenForms [0]'很好。 – bigtlb

+0

是的,這就是爲什麼我認爲找到控件是問題的一部分。 –