尝试将跨线程日志记录到ListView
private enum LogType {Info, Error, Warning};
private delegate void AddItemCallback(string line, LogType lt);
private void LogAddInfo(string line, LogType lt)
{
if (lvLog.InvokeRequired)
{
AddItemCallback d = new AddItemCallback(LogAddInfo);
this.Invoke(d, new { line, lt }); // <-- here is the problem
}
else
{
// code that adds item to listView (in this case $o)
lvLog.Items.Add(new ListViewItem(DateTime.Now.ToString(" HH:mm:ss ") + line, (int)lt));
}
}
这将使参数计数不匹配。如何正确声明新对象? 提前谢谢你,
答案 0 :(得分:1)
您需要更改此行:
this.Invoke(d, new { line, lt }); // <-- here is the problem
要:
this.Invoke(d, new object[] { line, lt });
// or
this.Invoke(d, line, lt);
您的版本将创建一个包含2个属性的匿名类,并将作为一个参数传递。这就是参数不匹配的原因。
你必须将它作为一个对象数组或两个独立的参数传递。
有用的提示。跨线程修改控件(使用调用)可能会松弛您的线程代码。问题是,foreach回调是一个调用。更好的方法是将信息存储在队列中并使用计时器来处理队列。
例如:
private class LogMessage
{
public DateTime CreatedOn {get;} = DateTime.Now;
public string Line {get;set;}
public LogType LogType {get; set;}
}
private List<LogMessage> _logQueue = new List<LogMessage>();
private void LogAddInfo(string line, LogType lt)
{
lock(_logQueue)
_logQueue.Add(new LogMessage { Line = line, LogType = lt });
}
private void Timer1_tick(object sender, EventArgs e)
{
LogMessage[] messages;
lock(_logQueue)
{
messages = _logQueue.ToArray();
_logQueue.Clear();
}
foreach(var msg in messages)
{
// add to listview
}
}
由于更少的更新,它会运行得更好。
答案 1 :(得分:1)
你也可以使用匿名委托和这样的递归调用:
private void LogAddInfo(string line, LogType lt)
{
if (lvLog.InvokeRequired)
{
lvLog.Invoke((MethodInvoker)delegate ()
{
this.LogAddInfo(line, lt);
});
}
else
{
// code that adds item to listView (in this case $o)
lvLog.Items.Add(new ListViewItem(DateTime.Now.ToString(" HH:mm:ss ") + line, (int)lt));
}
}