2014-03-28 125 views
1

在一個控制檯應用程序,我有一個名爲MyPolling其啓動時,監控外部資源,直到停止類。裏面的監視循環中,我使用注入實施ILogger的,該服務使用寫消息對輪詢類的狀態。爲什麼我的窗口沒有從我的線程更新?

有時我會想ILogger的實現寫入到控制檯,其他時間我可能要顯示一個窗口,也寫輸出到窗口除了控制檯。

然而,當我運行showLog = TRUE,沒有被更新visualLog窗口下面的(紡「等待」圖標)。對於showLog = {true,false}控制檯記錄器正在被正確更新。

很顯然,我有某種線程的問題,但我不知道我哪裏錯了。

static void Main(string[] args) 
    { 
     bool showLog = true; //obviously will set this from args 

     VisualLogger visualLogger = null; 
     ILogger logger; 
     if (showLog) 
     { 
      //create the visual logger, and use that to create the debug logger 
      visualLogger = new VisualLogger(); 
      logger = new DebugLogger(visualLogger); 
     } 
     else 
     { 
      //create the "normal" debug logger 
      logger = new DebugLogger(); 
     } 

     //create the polling class and inject the logger and then start the thread 
     var svc = new MyPolling(logger);   
     var pollThread = new Thread(new ThreadStart(svc.BeginPolling)); 
     pollThread.Start(); 

     //if the visualLogger wasnt created, don't show it. 
     if (visualLogger!=null) 
      visualLogger.Show(); 

     Console.ReadLine(); 
     svc.Dispose(); 
    } 

    public interface ILogger 
    { 
     void Write(string message); 
    } 

    public class DebugLogger : ILogger 
    { 
     private ILogger _baseLogger; 
     public DebugLogger(ILogger logger = null) 
     { 
      _baseLogger = logger; 
     } 

     public void Write(string message) 
     { 
      if (_baseLogger != null) 
       _baseLogger.Write(message); 

      Console.WriteLine(message); 
     } 
    } 

,我的實VisualLogger的:

public partial class VisualLogger : Form, ILogger 
{ 
    public VisualLogger() 
    { 
     InitializeComponent(); 
     txtLog.Clear(); 
    } 

    public void Write(string message) 
    { 
     txtLog.Text += message + Environment.NewLine; 
    } 
} 
+0

你得到任何異常?如果您在與UI線程不同的線程上工作,則需要在顯示消息之前調用UI線程。 –

回答

2

它來自Form需要消息循環來處理事件的事實。 Form.ShowDialog執行自己的消息循環,而Show不會。如果你從另一個表單調用Show方法,那麼就有一個消息循環,但是在你的情況下,你從控制檯應用程序調用它,你需要使用ShowDialog。你也不能從其他線程編輯UI控件,並且你需要Invoke方法。所以你需要這些變化:

public partial class VisualLogger : Form, ILogger 
{ 
    public VisualLogger() 
    { 
     InitializeComponent(); 
     txtLog.Clear(); 
    } 

    private void WriteInternal(string message) 
    { 
     txtLog.Text += message + Environment.NewLine; 
    } 

    public void Write(string message) 
    { 
     txtLog.Invoke(new Action<string>(WriteInternal), message); 
     // or simpler remove the WriteInternal function and use the next line: 
     // txtLog.Invoke(new Action(() => txtLog.Text += message + Environment.NewLine)); 
    } 
} 

在主營:

if (visualLogger != null) 
     visualLogger.ShowDialog(); 

或者,如果你想繼續你的主線程:

Thread t = new Thread(new ThreadStart(
     () => 
     { 
      if (visualLogger != null) 
       visualLogger.ShowDialog(); 
     })); 
    t.Start(); 
1

必須更新從UI線程的形式控制。像這樣的事情應該這樣做:

txtLog.Invoke((sender, args) => (sender as TextBox).Text = "text"); 
相關問題