在控制台应用程序中,我有一个名为 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 :(得分: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");