Method 1:
Use Invoke like Tigran describes.
For Winforms this would look like:
Thread t = new Thread(() =>
{
if (!Dispatcher.CurrentDispatcher.CheckAccess())
{
Dispatcher.CurrentDispatcher.BeginInvoke(
new Action(() =>
{
foreach (ListViewItem row in listView1.Items)
{
row.SubItems[0].Text = "Checking";
Thread.Sleep(2000);
}
}),
DispatcherPriority.ApplicationIdle,
null);
}
else
{
foreach (ListViewItem row in listView1.Items)
{
row.SubItems[0].Text = "Checking";
Thread.Sleep(2000);
}
}
});
t.Start();
The CheckAccess() Call returns true if called from the UI-Thread otherwise false.
The Dispatcher Class is located in the "System.Windows.Threading" Namespace in the "WindowsBase" NET. Assembly
Dispatcher info copied from: https://stackoverflow.com/a/4429009/1469035
Edit: Changed code to WinForms.
Edit: Code Fixed.
Method 2:
Use a Callback:
Untested Code:
public partial class Form1 : Form
{
private delegate void SetCallback(ListViewItem row, string text);
public Form1()
{
InitializeComponent();
}
private void SomeMethod()
{
Thread t = new Thread(() =>
{
foreach (ListViewItem row in listView1.Items)
{
if (listView1.InvokeRequired)
{
SetCallback d = new SetCallback(SetText);
this.Invoke(d, new object[] { row, "Checking" });
}
Thread.Sleep(2000);
}
});
t.Start();
}
private void SetText(ListViewItem row, string text)
{
row.SubItems[0].Text = text;
}
}
AFAIK readonly Access to Controls from Threads other than the UI-Thread is allowed in Winforms. So you can check any Control-Property you want and pass the required information to the Delegate.
And even if Reading doents work that way, you can just make another Delegate that has a return value. The Invoke() Method returns an object:
Similar to this:
private delegate object GetCallback(ListViewItem row);
private object o;
...
GetCallback g = new GetCallback(GetText);
o = this.Invoke(g, new object[] { row });
private string GetText(ListViewItem row)
{
return row.SubItems[0].Text;
}
Derived From: Link