2014-09-01 55 views
0

我正在用C#創建一個應該從不同程序調用的公共方法的dll。當程序調用這個方法時:'ShowMsg',它應該創建並顯示一個小表單(基本上是一個警告彈出框),並且根據消息的類型以特定的顏色顯示特定的消息。 表單應該保持可見,直到調用程序再次用不同的參數調用ShowMsg爲止,同樣的表單應該更新它的消息和顏色。C#class libary在單獨的線程上顯示和更新表單

我現在在調用程序是這樣的:

//Create the form here but do not show it yet 
AlertMsg alertMsg = new AlertMsg(); 

//Show the form with this message 
alertMsg.ShowMsg("message 1", "message 1 description", AlertMsg.MsgTypes.Warning); 

//do lengthy stuff, simulated with a sleep here 
System.Threading.Thread.Sleep(4000); 

//Update the form showing this message 
alertMsg.ShowMsg("message 2", "message 2 description", AlertMsg.MsgTypes.Critical); 

//do lengthy stuff, simulated with a sleep here 
System.Threading.Thread.Sleep(4000); 

我已經創造了從「ALERTMSG」,這看起來應該的方式。當我第一次打電話給.ShowMsg時,它也會顯示出來。只有表格上的標籤保持白色。另外,當我下次調用.ShowMsg時不會更新表單。

我認爲要解決這個問題,我應該創建一個單獨的線程上的窗體,但我不知道如何做到這一點。有人能指出我正確的方向嗎?

非常感謝。


我試過.Refresh提示,我得到了,現在我有這個。以上仍然是調用程序,並保持不變。現在

,在我的課ALERTMSG我(出留下了一些代碼爲簡潔起見)有這樣的:

public class AlertMsg 
{ 
    frmAlertMsg _frmAlertMsg; 

    public AlertMsg() 
    { 
     _frmAlertMsg = new frmAlertMsg(); 
    } 

    public void Show(string header, string text, MsgTypes msgType) 
    { 
     _frmAlertMsg.showMsg(header, text, msgType); 
    } 
} 

並在窗體類我有這樣的:

private void frmAlertMsg_Load(object sender, EventArgs e) 
{ 
    this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Right - 420, Screen.PrimaryScreen.WorkingArea.Bottom - 120); 
} 

internal void showMsg(string header, string text, AlertMsg.MsgTypes typeM) 
{ 
    //left out setting the colors part here 

    lblHeader.Text = header; 
    lblDescription.Text = text; 

    this.Show(); 
    this.Refresh();  
} 

這現在完美地顯示了標籤設置爲我給它的文本的形式。當我再次調用showMsg時,它也會更新。

所以再次感謝你。

+0

聽起來好像你是對的,你需要一個單獨的線程。首先用谷歌搜索「c#線程示例」,並嘗試一些在那裏的東西。如果遇到特定問題並無法解決問題,請回到SE併發布問題和問題代碼。 – 2014-09-01 18:49:47

+0

出於好奇,您是否在不顯示的控件上嘗試過一個簡單的「.Refresh()」?它在幾乎類似的情況下爲我工作。 – Larry 2014-09-01 19:19:42

+0

謝謝你所有的答案。其實,首先我只是嘗試.Refresh技巧,它的工作原理。實際上就像一個魅力! – Mytzenka 2014-09-02 16:32:12

回答

-1

簡單的解決方案是在窗體上繪畫後使用Application.DoEvents()。然而,將你長時間運行的任務放到單獨的線程當然是正確的選擇。

穿線例如:

//Create the form here but do not show it yet 
AlertMsg alertMsg = new AlertMsg(); 

//Show the form with this message 
alertMsg.ShowMsg("message 1", "message 1 description", AlertMsg.MsgTypes.Warning); 

ThreadStart ts = new ThreadStart(() => 
      { 
       //do lengthy stuff, simulated with a sleep here 
       System.Threading.Thread.Sleep(4000); 
       if (alertMsg.InvokeRequired) 
       { 
        this.Invoke(new Action(() => alertMsg.Hide())); 
       } 
      }); 
Thread th = new Thread(ts); 
th.Name = "longrunningtast"; 
th.Start(); 

不要忘了使用的invoke(),如果你有寫在新線程的形式。

+1

如果你不做任何事情,而是等待它完成調用線程,那麼創建一個新的線程是毫無意義的。 – Servy 2014-09-02 16:40:56

+0

感謝這個線程示例。它可能會在稍後派上用場。但現在我認爲我已經通過使用.Refresh提示充分解決了這個問題。但實際上,我不能在編碼程序中創建一個線程,因爲這將在VBScript中(在實際情況下),而且我非常確定它不支持線程。我在想的是創建顯示在線程中的窗體,並在窗體類的構造函數中創建該線程。但我不確定這是否正確。 – Mytzenka 2014-09-02 16:42:17

+0

@Servy如果你想發送狀態信息例如,並希望你的主線程和窗體在運行長時間任務時做出響應,這是一個解決方案。 – Perrier 2014-09-02 17:19:15

0

您不應該在另一個線程中創建表單,否。你應該有一個你的應用程序的UI線程,而不是幾個。如果你有非UI工作,你應該把工作分流到非UI線程。創建多個UI線程是一個真正的痛苦,你應該儘可能避免做。在UI線程中執行非UI工作時,創建一個新線程來完成UI工作,這爲您提供了比您需要的更多工作。

相反,你需要編寫你的程序異步。您不需要長時間阻塞UI線程並讓它抽取消息。

AlertMsg alertMsg = new AlertMsg(); 
alertMsg.ShowMsg("message 1", "message 1 description", 
    AlertMsg.MsgTypes.Warning); 

await Task.Run(() => SomeLongRunningOperation()); 

alertMsg.ShowMsg("message 2", "message 2 description", 
    AlertMsg.MsgTypes.Critical); 

await Task.Run(() => AnotherLongRunningOperation());