So I am using C# and Forms, I have ListView with Items and I am trying to find Item with text.
I have seperate threads in 2 seperate scripts/classes (1. MainForm.cs and 2. workWithLists.cs I need to use FindItemWithText in workWithLists.cs) so I need to use invoke:
ListViewItem v = listView1.Invoke(listView1.FindItemWithText("TestName"));
But I have error when I use Invoke with FindItemWithText:
Cannot convert from "System.Windows.Forms.ListViewItem" to "System.Delegate"
Without Invoke:
ListViewItem v = listView1.FindItemWithText("TestName");
I don't have any Errors, But when I run the code it gives me Error:
Invalid multi-thread operation: An attempt was made to access control 'listView1' from a thread other than the thread it was created on.
Please somebody explain to me what am I doing wrong, And how to fix this.
Calling FindItemWithText from the thread listview1 was made is not an Answer : D
Edit: I have this code in MainForm.cs:
public static ListView list;
public delegate void FindInListViewDelegate(string name);
public FindInListViewDelegate FindInListView = new FindInListViewDelegate(Find);
public ListViewItem Find(string name)
{
ListViewItem item = list.FindItemWithText(name);
return item;
}
But I am getting Error: A field initializer cannot reference the non-static field, method, or property 'MainForm.Find(string)'
I was changing:
public ListViewItem Find(string name) {}
To:
public static ListViewItem Find(string name) {}
But then it gives another Error: 'ListViewItem MainForm.Find(string)' has the wrong return type
CodePudding user response:
Control.Invoke method, executes a delegate on the thread that owns the control's underlying window handle.
And listView1.FindItemWithText is not a delegate, so in your main thread declare an Action or a delegate and use it in your second thread.
Main thread:
public delegate void FindInListViewDelegate(string name);
public FindInListViewDelegate FindInListView = new FindInListViewDelegate(Find);
public ListViewItem Find(string name)
{
var item = listView1.FindItemWitdhText(name);
...
}
Secondary thread:
myForm.Invoke(myForm.FindInListView, new object[] { nameToSearch });
You can use an Action too, I set up a small Console application:
internal class Program
{
static public Action<string> FindInListView = (name) =>
{
Console.WriteLine($"Finding item {name} in ListView");
};
static async Task Main(string[] args)
{
await new TaskFactory().StartNew(() => { FindInListView.Invoke("Joan"); });
return;
}
}