473,796 Members | 2,669 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

foreach listviewitem in a background thread

How can I have access to the items collection of a listview control on
my form from a background thread?

I know I need delegates to update the listview control and I have those
calls in the foreach loop, but I'm not sure how to access the items
collection.

foreach (ListViewItem li in this.listview1. Items)
{
Invoke(new deleg(updatectr l), new object [] { param });
}

Thanks!
May 15 '07 #1
13 10235
On Tue, 15 May 2007 14:53:01 -0500, deciacco <a@awrote:
>How can I have access to the items collection of a listview control on
my form from a background thread?

I know I need delegates to update the listview control and I have those
calls in the foreach loop, but I'm not sure how to access the items
collection.

foreach (ListViewItem li in this.listview1. Items)
{
Invoke(new deleg(updatectr l), new object [] { param });
}

Thanks!
out of my head: you execute a method Safemethod, if it's called from
another thread InvokeRequired will be true and de method will be
called again but this time from within the UI thread, and the foreach
loop can be used safely.
private void SafeMethod ( )
{
if ( this.InvokeRequ ired )
this.Invoke( new SafeMethodDeleg ate ( SafeMethod ) );
else
{
foreach (ListViewItem li in this.listview1. Items)
{
// do sth with li
}
}
}

private delegate void SafeMethodDeleg ate ( );

--
Ludwig
http://www.coders-lab.be
May 15 '07 #2
I don't think this will work for me, because I don't want the foreach to
be executed on the main thread. I need the foreach to stay in it's own
thread and inside the foreach have calls to thread-safe methods. The
problem is that I need the worker thread to have information about the
listbox so it can pass on information to the thread safe functions to do
their jobs.

For example, for each one of the items in the list I want a worker
thread to call setImageForList ViewItem and pass in the current item
index and the index of the image to use for that item.

foreach (ListViewItem li in this.listviewPr ogress.Items)
{
Invoke(new setImageForList ViewItemDelg(se tImageForListVi ewItem), new
object[] { 2, li.Index });
}

Thanks.

Ludwig wrote:
On Tue, 15 May 2007 14:53:01 -0500, deciacco <a@awrote:
>How can I have access to the items collection of a listview control on
my form from a background thread?

I know I need delegates to update the listview control and I have those
calls in the foreach loop, but I'm not sure how to access the items
collection.

foreach (ListViewItem li in this.listview1. Items)
{
Invoke(new deleg(updatectr l), new object [] { param });
}

Thanks!

out of my head: you execute a method Safemethod, if it's called from
another thread InvokeRequired will be true and de method will be
called again but this time from within the UI thread, and the foreach
loop can be used safely.
private void SafeMethod ( )
{
if ( this.InvokeRequ ired )
this.Invoke( new SafeMethodDeleg ate ( SafeMethod ) );
else
{
foreach (ListViewItem li in this.listview1. Items)
{
// do sth with li
}
}
}

private delegate void SafeMethodDeleg ate ( );


May 15 '07 #3
On Tue, 15 May 2007 14:40:44 -0700, deciacco <a@awrote:
I don't think this will work for me, because I don't want the foreach to
be executed on the main thread. I need the foreach to stay in it's own
thread and inside the foreach have calls to thread-safe methods. The
problem is that I need the worker thread to have information about the
listbox so it can pass on information to the thread safe functions to do
their jobs.
Can you clarify what about the goal is giving you trouble?

I see two possible issues, at least. One is synchronizing access to the
Items collection. The other is making sure your delegate gets invoked on
the ListView control for each item. But since as far as I know you're not
trying to modify the collection while the thread runs, and you *do* show
us a call to Invoke in your example, I don't really see what the problem
is. (The Invoke appears to be on the owning control, probably a Form, but
that should put you on the correct thread anyway).

What exactly is it you want the worker thread to do that you're not able
to do, and why aren't you able to do it (the second part of that question
is as important as the first IMHO)?

Pete
May 15 '07 #4
Ok...I'm having trouble explaining myself...
Here is the end result:

I have a list of items in a listview control. Each item in the list is a
task that the worker thread needs to accomplish. When the work thread is
on a list item I want the worker thread to change the icon of that list
item to show "currently executing". After that task is executed I want
the worker thread to change the item's icon to show "task completed
sucessfully" or "task had a problem".
Peter Duniho wrote:
On Tue, 15 May 2007 14:40:44 -0700, deciacco <a@awrote:
>I don't think this will work for me, because I don't want the foreach
to be executed on the main thread. I need the foreach to stay in it's
own thread and inside the foreach have calls to thread-safe methods.
The problem is that I need the worker thread to have information about
the listbox so it can pass on information to the thread safe functions
to do their jobs.

Can you clarify what about the goal is giving you trouble?

I see two possible issues, at least. One is synchronizing access to the
Items collection. The other is making sure your delegate gets invoked
on the ListView control for each item. But since as far as I know
you're not trying to modify the collection while the thread runs, and
you *do* show us a call to Invoke in your example, I don't really see
what the problem is. (The Invoke appears to be on the owning control,
probably a Form, but that should put you on the correct thread anyway).

What exactly is it you want the worker thread to do that you're not able
to do, and why aren't you able to do it (the second part of that
question is as important as the first IMHO)?

Pete
May 15 '07 #5
On Tue, 15 May 2007 15:31:09 -0700, deciacco <a@awrote:
Ok...I'm having trouble explaining myself...
Here is the end result:

I have a list of items in a listview control. Each item in the list isa
task that the worker thread needs to accomplish. When the work thread is
on a list item I want the worker thread to change the icon of that list
item to show "currently executing". After that task is executed I want
the worker thread to change the item's icon to show "task completed
sucessfully" or "task had a problem".
Okay. :)

So, the basic idea IMHO is that each thread should include as part of its
state information the ListViewItem you want to update (initialized when
you start the thread, using the usual thread initialization mechanisms).
Then, when you want to update the visual state of the ListViewItem, call
Invoke() or BeginInvoke() on the ListView itself (which you can get from
the ListViewItem), to execute a delegate that updates the ListViewItem as
you desire.

For example:

private ListViewItem _lvi;

private void _StartWork()
{
_lvi.ListView.I nvoke(delegate () { _lvi.ImageIndex = kiimgWorking;
});
}

private void _EndWork()
{
_lvi.ListView.I nvoke(delegate () { _lvi.ImageIndex =
kiimgCompleted; });
}

(where you've set up an appropriate ImageList containing your icons, and
the kiimgWorking and kiimgCompleted constants correspond to the
appropriate image indices)

You'd call _StartWork() at the beginning of your worker thread processing
method, and _EndWork() at the end.

If that doesn't help, then you'll probably have to provide more details.

Pete
May 15 '07 #6
Peter,
Thanks so much for your reply, I will give it a try and report back.
Really appreciate the help with this stuff!!

Peter Duniho wrote:
On Tue, 15 May 2007 15:31:09 -0700, deciacco <a@awrote:
>Ok...I'm having trouble explaining myself...
Here is the end result:

I have a list of items in a listview control. Each item in the list is
a task that the worker thread needs to accomplish. When the work
thread is on a list item I want the worker thread to change the icon
of that list item to show "currently executing". After that task is
executed I want the worker thread to change the item's icon to show
"task completed sucessfully" or "task had a problem".

Okay. :)

So, the basic idea IMHO is that each thread should include as part of
its state information the ListViewItem you want to update (initialized
when you start the thread, using the usual thread initialization
mechanisms). Then, when you want to update the visual state of the
ListViewItem, call Invoke() or BeginInvoke() on the ListView itself
(which you can get from the ListViewItem), to execute a delegate that
updates the ListViewItem as you desire.

For example:

private ListViewItem _lvi;

private void _StartWork()
{
_lvi.ListView.I nvoke(delegate () { _lvi.ImageIndex =
kiimgWorking; });
}

private void _EndWork()
{
_lvi.ListView.I nvoke(delegate () { _lvi.ImageIndex =
kiimgCompleted; });
}

(where you've set up an appropriate ImageList containing your icons, and
the kiimgWorking and kiimgCompleted constants correspond to the
appropriate image indices)

You'd call _StartWork() at the beginning of your worker thread
processing method, and _EndWork() at the end.

If that doesn't help, then you'll probably have to provide more details.

Pete
May 16 '07 #7
Peter,

This is what I'm trying to do:
When the form loads, the listbox is populated with the tasks.
Then a new thread is started to go through those tasks one by one in order.

private delegate void setStatusImageD elegate(int imgIndex, int listItemIndex);

Thread t = new Thread(new ThreadStart(exe cuteTasksInOrde r));
t.IsBackground = true;
t.Start();

private void executeTasksInO rder()
{
foreach (ListViewItem li in this.listviewPr ogress.Items) //<--Can't access listview from thread
{
this.Invoke(new setStatusImageD elegate(setStat usImage), new object[] { 0, li.Index} );
Thread.Sleep(20 00); // <--For testing
this.Invoke(new setStatusImageD elegate(setStat usImage), new object[] { 2, li.Index });
}
}

private void setStatusImage( int imgIndex, int listItemIndex)
{
this.listviewPr ogress.Items[listItemIndex].ImageIndex = imgIndex;
}
Peter Duniho wrote:
On Tue, 15 May 2007 15:31:09 -0700, deciacco <a@awrote:
>Ok...I'm having trouble explaining myself...
Here is the end result:

I have a list of items in a listview control. Each item in the list is
a task that the worker thread needs to accomplish. When the work
thread is on a list item I want the worker thread to change the icon
of that list item to show "currently executing". After that task is
executed I want the worker thread to change the item's icon to show
"task completed sucessfully" or "task had a problem".

Okay. :)

So, the basic idea IMHO is that each thread should include as part of
its state information the ListViewItem you want to update (initialized
when you start the thread, using the usual thread initialization
mechanisms). Then, when you want to update the visual state of the
ListViewItem, call Invoke() or BeginInvoke() on the ListView itself
(which you can get from the ListViewItem), to execute a delegate that
updates the ListViewItem as you desire.

For example:

private ListViewItem _lvi;

private void _StartWork()
{
_lvi.ListView.I nvoke(delegate () { _lvi.ImageIndex =
kiimgWorking; });
}

private void _EndWork()
{
_lvi.ListView.I nvoke(delegate () { _lvi.ImageIndex =
kiimgCompleted; });
}

(where you've set up an appropriate ImageList containing your icons, and
the kiimgWorking and kiimgCompleted constants correspond to the
appropriate image indices)

You'd call _StartWork() at the beginning of your worker thread
processing method, and _EndWork() at the end.

If that doesn't help, then you'll probably have to provide more details.

Pete
May 16 '07 #8
On Wed, 16 May 2007 07:55:08 -0700, deciacco <a@awrote:
This is what I'm trying to do:
When the form loads, the listbox is populated with the tasks.
Then a new thread is started to go through those tasks one by one in
order.
Ahh...I see. I misunderstood, and thought you had one thread per task.
And now I see why you're having so much trouble. You get the cross-thread
access not allowed exception when you try to access the collection of
Items in the ListView object.

For what it's worth, you might have been more clear about that (as in,
actually describe the error you got :) ).

Anyway, now that we're on the same page...

You can address the issue in a variety of ways. You could use Invoke to
go back and forth, using it to get the count of items and then to get each
individual one based on an index. Or you could just build the list of the
items and pass that to the thread when you initialized is (using the
parameter start version of the thread constructor and start method). Or
you could build an "enumerator by proxy" into the form's class that would
allow you to use the IEnumerable interface to handle the foreach()
transparently (that interface would handle the invoking required to
extract the necessary item at the appropriate moment).

Here's an example of the first method I describe (note that this is the
first time I've had to deal with ref or out parameters using the Invoke
method, so I can't vouch that I've done it in the best or cleanest
way...but it does work :) ):

private delegate void SetIndexHandler ();
private delegate void GetItemHandler( int iitem, out ListViewItem
item);
private delegate void GetCountHandler (out int count);

private void _MyThread()
{
int citem;
object[] parmsGetCount = new object[1];
object[] parmsGetItem = new object[2];

// Use Invoke to get the current count of items in the list
listView1.Invok e(new GetCountHandler (delegate(out int
countOut) { countOut = listView1.Items .Count; }), parmsGetCount);
citem = (int)parmsGetCo unt[0];

for (int iitem = 0; iitem < citem; iitem++)
{
ListViewItem lvi;

// Use Invoke to get a ListViewItem given the current index
// Note: this doesn't do any checking to make sure the
list
// hasn't changed since you got the count. In real code
you
// would probably want to range check the input :).
parmsGetItem[0] = iitem;
listView1.Invok e(new GetItemHandler( delegate(int iitemGet,
out ListViewItem itemOut) { itemOut = listView1.Items[iitemGet]; }),
parmsGetItem);
lvi = (ListViewItem)p armsGetItem[1];

// Use Invoke to actually change the image index
listView1.Invok e(new SetIndexHandler (delegate()
{ lvi.ImageIndex = 0; }));
Thread.Sleep(20 00);
listView1.Invok e(new SetIndexHandler (delegate()
{ lvi.ImageIndex = 1; }));
}
}

Of course, the above code requires that you've set up your ListView with
the appropriate image list and items. I didn't bother to paste in all of
the rest of the code for the form, but hopefully you get the idea.

Pete
May 16 '07 #9
Thank you so much...this is great!
Just one thing I don't understand.

If I were to change your code a little and do something like this:

************
private delegate void GetCountHandler (out int count);

this.listviewPr ogress.Invoke(n ew GetCountHandler (getListViewCou nt), parmsGetCount);

private void getListViewCoun t(out int countOut)
{
countOut = this.listviewPr ogress.Items.Co unt;
}
************

Everything is fine, works great.

The same is not true of this line of code:
I know it works and I understand that you are creating the delegate on the fly, but
is there a way to do it like above?

************
this.listviewPr ogress.Invoke(n ew SetIndexHandler (delegate() { lvi.ImageIndex = 0; }));
************

I was thinking something like this:

************
private delegate void setScriptStatus ImageDelegate(i nt imgIndex, int listItemIndex);

this.listviewPr ogress.Invoke(n ew setScriptStatus ImageDelegate(s etScriptStatusI mage), new object[] { 0, lvi.Index });

private void setScriptStatus Image(int imgIndex, int listItemIndex)
{
this.listviewPr ogress.Items[listItemIndex].ImageIndex = imgIndex;
}
************

The problem is, I still get the cross-thread error on lvi.Index.
I thought I should be able to pass in lvi.Index since I used a delegate to get lvi.
Peter Duniho wrote:
On Wed, 16 May 2007 07:55:08 -0700, deciacco <a@awrote:
>This is what I'm trying to do:
When the form loads, the listbox is populated with the tasks.
Then a new thread is started to go through those tasks one by one in
order.

Ahh...I see. I misunderstood, and thought you had one thread per task.
And now I see why you're having so much trouble. You get the
cross-thread access not allowed exception when you try to access the
collection of Items in the ListView object.

For what it's worth, you might have been more clear about that (as in,
actually describe the error you got :) ).

Anyway, now that we're on the same page...

You can address the issue in a variety of ways. You could use Invoke to
go back and forth, using it to get the count of items and then to get
each individual one based on an index. Or you could just build the list
of the items and pass that to the thread when you initialized is (using
the parameter start version of the thread constructor and start
method). Or you could build an "enumerator by proxy" into the form's
class that would allow you to use the IEnumerable interface to handle
the foreach() transparently (that interface would handle the invoking
required to extract the necessary item at the appropriate moment).

Here's an example of the first method I describe (note that this is the
first time I've had to deal with ref or out parameters using the Invoke
method, so I can't vouch that I've done it in the best or cleanest
way...but it does work :) ):

private delegate void SetIndexHandler ();
private delegate void GetItemHandler( int iitem, out ListViewItem
item);
private delegate void GetCountHandler (out int count);

private void _MyThread()
{
int citem;
object[] parmsGetCount = new object[1];
object[] parmsGetItem = new object[2];

// Use Invoke to get the current count of items in the list
listView1.Invok e(new GetCountHandler (delegate(out int
countOut) { countOut = listView1.Items .Count; }), parmsGetCount);
citem = (int)parmsGetCo unt[0];

for (int iitem = 0; iitem < citem; iitem++)
{
ListViewItem lvi;

// Use Invoke to get a ListViewItem given the current index
// Note: this doesn't do any checking to make sure the
list
// hasn't changed since you got the count. In real code
you
// would probably want to range check the input :).
parmsGetItem[0] = iitem;
listView1.Invok e(new GetItemHandler( delegate(int
iitemGet, out ListViewItem itemOut) { itemOut =
listView1.Items[iitemGet]; }), parmsGetItem);
lvi = (ListViewItem)p armsGetItem[1];

// Use Invoke to actually change the image index
listView1.Invok e(new SetIndexHandler (delegate() {
lvi.ImageIndex = 0; }));
Thread.Sleep(20 00);
listView1.Invok e(new SetIndexHandler (delegate() {
lvi.ImageIndex = 1; }));
}
}

Of course, the above code requires that you've set up your ListView with
the appropriate image list and items. I didn't bother to paste in all
of the rest of the code for the form, but hopefully you get the idea.

Pete
May 17 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
323
by: Ahsan | last post by:
I have created some background threads so that when the application aborts all the threads should be automatically aborted. But the problem is that when I make a thread background thread I am unable to correctly find its thread state as the thread state property always return 12. If I make the thread foreground the thread state property works just fine. Please help me in finding the solution.
2
5471
by: jam | last post by:
dear all, could anyone help me about telling me how can i make a background thread displaying loading... when I cam calling a console application?? thanks.. jam
1
7002
by: Ioannis Vranos | last post by:
In .NET, what happens when a background thread and a foreground thread have the same priority (e.g. Normal). Do they share the same processor time? -- Ioannis Vranos
0
1033
by: Bil Muh | last post by:
Hello Developers, I would like to fill a data grid on my "Windows Forms (.NET)" by a background thread. I read some data from a binary file. With the information read from this file, I create Columns and Rows dynamically, then I fill them. I can do this operation. But, when the numbers of rows and columns are much, my application uses the 99% of CPU and stops working for other works. Fot this reason, I tried to assign this job to a...
0
1734
by: JC Voon | last post by:
Hi All: I'm new in Threading and Web Services, can someone please verify my code, i'm not sure whether this is the correct way, althought it is partially work, but some time it will raise exception at FillDatatable dr.AcceptChanges, and also the XTraGridControl will not response when click on the column header to do sorting and filtering. What i'm trying to do is very simple, i just want to retrieve a very large table from web service...
1
4252
by: JEB | last post by:
I know that with Web Services, you should be doing everything in a stateless environment. However, I have three methods out of over 100 that need state. I have the client cookie container, WebMethod with Session enabled = true, the works. However, my issue is I am running logic on a background thread in a managed thread pool and I cannot access the session. I cannot pass all the data into the thread either. Is there a way to access...
8
12099
by: mtsweep | last post by:
Hi, I started a background thread to preform some time intensive tasks for a GUI frontend. This background thread uses a C++ object which requires a windows message loop so I started one in it by calling Application.Run(). Now I can see that messages from the C++ libraries are being processed. But how do I send my own messages to this thread from the GUI frontend? I tried to use delegates/events/etc but it ends up either spawning a...
8
5372
by: =?Utf-8?B?R3JlZyBMYXJzZW4=?= | last post by:
I'm trying to figure out how to modify a panel (panel1) from a backgroundworker thread. But can't get the panel to show the new controls added by the backgroundwork task. Here is my code. In this code there is a panel panel1, that I populate with a lable in the foreground. Then when I click on "button1" a backgroundworker thread in async mode is started. When the backgoundworker thread completes the thread returns a panel to populate...
1
1875
by: Matt | last post by:
I've written a class that allows me to add documents to a SharePoint Document Library from another web application. The web app runs under a domain account that has permissions to SharePoint. However, when I try to do this from a background thread it fails with Access Denied. I've tested the WindowsIdentity from the background thread and it is the same. Are background threads not running in the same security context under ASP.NET 2.0? ...
0
9684
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9530
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10459
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10236
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10182
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10017
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9055
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6793
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
2
3734
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.