为什么我的窗口没有更新我的窗口?

时间:2014-03-28 18:18:50

标签: c# multithreading winforms

在控制台应用程序中,我有一个名为 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;
    }
}

2 个答案:

答案 0 :(得分: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 :(得分:1)

您必须从UI线程更新表单控件。这样的事情应该这样做:

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