Populating a listview from another thread
10,266
Solution 1
Usually I'm doing it like this:
using System;
using System.Windows.Forms;
namespace TestWinFormsThreding
{
class TestFormControlHelper
{
delegate void UniversalVoidDelegate();
/// <summary>
/// Call form control action from different thread
/// </summary>
public static void ControlInvoke(Control control, Action function)
{
if (control.IsDisposed || control.Disposing)
return;
if (control.InvokeRequired)
{
control.Invoke(new UniversalVoidDelegate(() => ControlInvoke(control, function)));
return;
}
function();
}
}
public partial class TestMainForm : Form
{
// ...
// This will be called from thread not the same as MainForm thread
private void TestFunction()
{
TestFormCotrolHelper.ControlInvoke(listView1, () => listView1.Items.Add("Test"));
}
//...
}
}
Solution 2
A simple search here on SO would have brought up many results that tell you that it is not allowed to change a GUI control from a thread other than the thread which created the control (cross-thread GUI access).
To do so, everything related to updating the ListView
must be done using this.Invoke
or this.Dispatcher.Invoke
(in WPF).
EDIT
For example this thread here.
Sample code:
private delegate void MyDelegate(string s);
public void UpdateControl(Control targetControl, string text)
{
if (targetControl.InvokeRequired)
{
// THIS IS STILL THE IN THE CONTEXT OF THE THREAD
MyDelegate call = new MyDelegate(UpdateControl);
targetControl.Invoke(call, new object[] { text });
}
else
{
// do control stuff
// THIS IS IN THE CONTEXT OF THE UI THREAD
}
}
Author by
XandrUu
Updated on August 04, 2022Comments
-
XandrUu over 1 year
I'm trying to populate a listview from another class, but I'm geting this error: " Cross-thread operation not valid: Control 'listView1' accessed from a thread other than the thread it was created on. "
In my class I declare my listview like this:
class CheckBlankPages { public String[] pdfFiles { get; set; } ListView _ListVireRef; public int NrCRT = 1; public CheckBlankPages(String[] pdfFiles = null, ListView listView = null) { this.pdfFiles = pdfFiles; _ListVireRef = listView; } public void StartCheckingPDF() { foreach (string pdf in pdfFiles) { String[] itm = { (NrCRT++).ToString(), pdf }; ListViewItem item = new ListViewItem(itm); _ListVireRef.Items.Add(item); } } }
and in my MainForm I use this code:
DialogResult rezultat = openFileDialog1.ShowDialog(); if (rezultat == DialogResult.OK) { CheckBlankPages ck = new CheckBlankPages(openFileDialog1.FileNames, listView1); Thread CheckPDFs = new Thread(new ThreadStart(ck.StartCheckingPDF)); CheckPDFs.Start(); }
What is wrong?