c#ListView交叉线程,委托不工作

时间:2017-03-29 14:30:21

标签: c# listview

尝试将跨线程日志记录到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));
    }

}

这将使参数计数不匹配。如何正确声明新对象? 提前谢谢你,

2 个答案:

答案 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));
        }
    }