Reputation: 1669
Trying to make a cross thread log to 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));
}
}
This will give a parameter count mismatch. How to declare the new object properly? Thank you in advance,
Upvotes: 1
Views: 751
Reputation: 22038
You need to change this line:
this.Invoke(d, new { line, lt }); // <-- here is the problem
To:
this.Invoke(d, new object[] { line, lt });
// or
this.Invoke(d, line, lt);
Your version will create an anonymous class with 2 properties and will be passed as one parameter. Thats why the parameter mismatch.
You'll have to pass it as an array of objects or two separated parameters.
A usefull tip. Cross-threading modifying controls (with invoke) could slack up your thread code. The problem is, that foreach callback an invoke is made. A better way is to store the info in a queue and use a timer to process the queue.
For example:
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
}
}
It will run much better due to less hui updates.
Upvotes: 1
Reputation: 39132
You can also just use an anonymous delegate and a recursive call like this:
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));
}
}
Upvotes: 1