2014-03-28 89 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"); 
相关问题