Connecting Tech Pros Worldwide Forums | Help | Site Map

Threading with UI elements - dynamically created controls?

RCS
Guest
 
Posts: n/a
#1: Nov 16 '05

I have a UI that needs a couple of threads to do some significant processing
on a couple of different forms - and while it's at it, update the UI (set
textboxes, fill in listviews). I created a base class for the worker class,
and made up some functions/delegates to handle the invoke stuff for the UI
and that was fine for a prototype. I rewrote this chunk, broke things out
into different classes - but the threading is still the same - and one
specific problem I'm having is this.

Within the worker thread, I do this:

ListViewItem lvwItem = new ListViewItem();

I want to try to do as much work as possible, while leaving a lot of
potential functionality in the worker thread. So I'd like to pre-populate a
ListViewItem - and then do the Invoke to just add that pre-filled
ListViewItem to the listview on the UI.

On that line, I get an error of:

Illegal cross-thread operation: Control 'frmPopup' accessed from a thread
other than the thread it was created on.
Stack trace where the illegal operation occurred was:

at System.Windows.Forms.Control.get_Handle() etc, etc

And it happens right at that line above when I'm trying to create a
ListViewItem programatically. I am assuming that when you create a UI
element programatically, it needs a window handle? If so - how do I get
around this? And I know I've had this work before, the only thing different
is I have this functionality in a seperate class.

Also - I got rid of 100% of the functionality in that thread (commented it
out) - and slowly added lines back in, and this is the only, even remote
reference to a UI element in this chunk of code, and this is the specific
line that throws the exception.

Any ideas???



Elidel
Guest
 
Posts: n/a
#2: Nov 16 '05

re: Threading with UI elements - dynamically created controls?



I don't know how your creating your thread, but it sounds like the error is
in how you pass back the result to the main ( calling ) thread.

So, for example, if you try to add lvwItem to frmPopup in the spawned thread
you might get that error.

If you set up, say, a thread pool, that calls a method that returns
ListViewItem as a result, and then add it to frmPopup control array, that
might be different.

RCS wrote:
[color=blue]
>
> I have a UI that needs a couple of threads to do some significant
> processing on a couple of different forms - and while it's at it, update
> the UI (set textboxes, fill in listviews). I created a base class for the
> worker class, and made up some functions/delegates to handle the invoke
> stuff for the UI and that was fine for a prototype. I rewrote this chunk,
> broke things out into different classes - but the threading is still the
> same - and one specific problem I'm having is this.
>
> Within the worker thread, I do this:
>
> ListViewItem lvwItem = new ListViewItem();
>
> I want to try to do as much work as possible, while leaving a lot of
> potential functionality in the worker thread. So I'd like to pre-populate
> a ListViewItem - and then do the Invoke to just add that pre-filled
> ListViewItem to the listview on the UI.
>
> On that line, I get an error of:
>
> Illegal cross-thread operation: Control 'frmPopup' accessed from a thread
> other than the thread it was created on.
> Stack trace where the illegal operation occurred was:
>
> at System.Windows.Forms.Control.get_Handle() etc, etc
>
> And it happens right at that line above when I'm trying to create a
> ListViewItem programatically. I am assuming that when you create a UI
> element programatically, it needs a window handle? If so - how do I get
> around this? And I know I've had this work before, the only thing
> different is I have this functionality in a seperate class.
>
> Also - I got rid of 100% of the functionality in that thread (commented it
> out) - and slowly added lines back in, and this is the only, even remote
> reference to a UI element in this chunk of code, and this is the specific
> line that throws the exception.
>
> Any ideas???[/color]

--
Texeme
http://texeme.com

RCS
Guest
 
Posts: n/a
#3: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


Windows doesn't allow a secondary thread to update any UI elements. You have
to have the original UI thread do that. So what you can do from the
secondary thread is:

if ( InvokeRequired )
{
BeginInvoke(...)
}
// Do the real work here


That part of this, is all good and works fine. There is somewhat of a
detailed class that handles all the UI elements that I'd need to update from
a background thread. But way before I get to that, and to address what
you've asked. From the UI thread I do this to start things off:


System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
LoadListView1 );
System.Threading.Thread objThread = new System.Threading.Thread( objTS );
objThread.Name = "LoadListView1";
objThread.Start();


Then, within that function, I am immediately doing this:


ListViewItem lvwItem = new ListViewItem();


That is enough to make it fail. So, I'm not actually trying to update any UI
elements on a form, at this point - I'm just programatically creating a UI
element that will be added to one of my forms later.



"Elidel" <im@elidel.l.eh.del> wrote in message
news:rX8Nd.1166$UX3.1062@newsread3.news.pas.earthl ink.net...[color=blue]
>
> I don't know how your creating your thread, but it sounds like the error
> is
> in how you pass back the result to the main ( calling ) thread.
>
> So, for example, if you try to add lvwItem to frmPopup in the spawned
> thread
> you might get that error.
>
> If you set up, say, a thread pool, that calls a method that returns
> ListViewItem as a result, and then add it to frmPopup control array, that
> might be different.
>
> RCS wrote:
>[color=green]
>>
>> I have a UI that needs a couple of threads to do some significant
>> processing on a couple of different forms - and while it's at it, update
>> the UI (set textboxes, fill in listviews). I created a base class for the
>> worker class, and made up some functions/delegates to handle the invoke
>> stuff for the UI and that was fine for a prototype. I rewrote this chunk,
>> broke things out into different classes - but the threading is still the
>> same - and one specific problem I'm having is this.
>>
>> Within the worker thread, I do this:
>>
>> ListViewItem lvwItem = new ListViewItem();
>>
>> I want to try to do as much work as possible, while leaving a lot of
>> potential functionality in the worker thread. So I'd like to pre-populate
>> a ListViewItem - and then do the Invoke to just add that pre-filled
>> ListViewItem to the listview on the UI.
>>
>> On that line, I get an error of:
>>
>> Illegal cross-thread operation: Control 'frmPopup' accessed from a thread
>> other than the thread it was created on.
>> Stack trace where the illegal operation occurred was:
>>
>> at System.Windows.Forms.Control.get_Handle() etc, etc
>>
>> And it happens right at that line above when I'm trying to create a
>> ListViewItem programatically. I am assuming that when you create a UI
>> element programatically, it needs a window handle? If so - how do I get
>> around this? And I know I've had this work before, the only thing
>> different is I have this functionality in a seperate class.
>>
>> Also - I got rid of 100% of the functionality in that thread (commented
>> it
>> out) - and slowly added lines back in, and this is the only, even remote
>> reference to a UI element in this chunk of code, and this is the specific
>> line that throws the exception.
>>
>> Any ideas???[/color]
>
> --
> Texeme
> http://texeme.com
>[/color]


Elidel
Guest
 
Posts: n/a
#4: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


RCS wrote:
[color=blue]
> Windows doesn't allow a secondary thread to update any UI elements.[/color]

I'm not saying it should.

I'm saying you can return a new object -- which has the values you want, and
then in the main thread, update the UI element with that value.

[color=blue]
> You
> have to have the original UI thread do that. So what you can do from the
> secondary thread is:
>
> if ( InvokeRequired )
> {
> BeginInvoke(...)
> }
> // Do the real work here
>
>
> That part of this, is all good and works fine. There is somewhat of a
> detailed class that handles all the UI elements that I'd need to update
> from a background thread. But way before I get to that, and to address
> what you've asked. From the UI thread I do this to start things off:
>
>
> System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
> LoadListView1 );
> System.Threading.Thread objThread = new System.Threading.Thread( objTS );
> objThread.Name = "LoadListView1";
> objThread.Start();
>
>
> Then, within that function, I am immediately doing this:
>
>
> ListViewItem lvwItem = new ListViewItem();
>
>
> That is enough to make it fail. So, I'm not actually trying to update any
> UI elements on a form, at this point - I'm just programatically creating a
> UI element that will be added to one of my forms later.
>
>
>
> "Elidel" <im@elidel.l.eh.del> wrote in message
> news:rX8Nd.1166$UX3.1062@newsread3.news.pas.earthl ink.net...[color=green]
>>
>> I don't know how your creating your thread, but it sounds like the error
>> is
>> in how you pass back the result to the main ( calling ) thread.
>>
>> So, for example, if you try to add lvwItem to frmPopup in the spawned
>> thread
>> you might get that error.
>>
>> If you set up, say, a thread pool, that calls a method that returns
>> ListViewItem as a result, and then add it to frmPopup control array, that
>> might be different.
>>
>> RCS wrote:
>>[color=darkred]
>>>
>>> I have a UI that needs a couple of threads to do some significant
>>> processing on a couple of different forms - and while it's at it, update
>>> the UI (set textboxes, fill in listviews). I created a base class for
>>> the worker class, and made up some functions/delegates to handle the
>>> invoke stuff for the UI and that was fine for a prototype. I rewrote
>>> this chunk, broke things out into different classes - but the threading
>>> is still the same - and one specific problem I'm having is this.
>>>
>>> Within the worker thread, I do this:
>>>
>>> ListViewItem lvwItem = new ListViewItem();
>>>
>>> I want to try to do as much work as possible, while leaving a lot of
>>> potential functionality in the worker thread. So I'd like to
>>> pre-populate a ListViewItem - and then do the Invoke to just add that
>>> pre-filled ListViewItem to the listview on the UI.
>>>
>>> On that line, I get an error of:
>>>
>>> Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>> thread other than the thread it was created on.
>>> Stack trace where the illegal operation occurred was:
>>>
>>> at System.Windows.Forms.Control.get_Handle() etc, etc
>>>
>>> And it happens right at that line above when I'm trying to create a
>>> ListViewItem programatically. I am assuming that when you create a UI
>>> element programatically, it needs a window handle? If so - how do I get
>>> around this? And I know I've had this work before, the only thing
>>> different is I have this functionality in a seperate class.
>>>
>>> Also - I got rid of 100% of the functionality in that thread (commented
>>> it
>>> out) - and slowly added lines back in, and this is the only, even remote
>>> reference to a UI element in this chunk of code, and this is the
>>> specific line that throws the exception.
>>>
>>> Any ideas???[/color]
>>
>> --
>> Texeme
>> http://texeme.com
>>[/color][/color]

--
Texeme
http://texeme.com

Elidel
Guest
 
Posts: n/a
#5: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


RCS wrote:

[color=blue]
> System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
> LoadListView1 );
> System.Threading.Thread objThread = new System.Threading.Thread( objTS );
> objThread.Name = "LoadListView1";
> objThread.Start();
>
>
> Then, within that function, I am immediately doing this:
>
>
> ListViewItem lvwItem = new ListViewItem();[/color]


And you then get the error:


[color=blue]
>
>
> That is enough to make it fail. So, I'm not actually trying to update any
> UI elements on a form, at this point - I'm just programatically creating a
> UI element that will be added to one of my forms later.
>
>
>
> "Elidel" <im@elidel.l.eh.del> wrote in message
> news:rX8Nd.1166$UX3.1062@newsread3.news.pas.earthl ink.net...[color=green]
>>
>> I don't know how your creating your thread, but it sounds like the error
>> is
>> in how you pass back the result to the main ( calling ) thread.
>>
>> So, for example, if you try to add lvwItem to frmPopup in the spawned
>> thread
>> you might get that error.
>>
>> If you set up, say, a thread pool, that calls a method that returns
>> ListViewItem as a result, and then add it to frmPopup control array, that
>> might be different.
>>
>> RCS wrote:
>>[color=darkred]
>>>
>>> I have a UI that needs a couple of threads to do some significant
>>> processing on a couple of different forms - and while it's at it, update
>>> the UI (set textboxes, fill in listviews). I created a base class for
>>> the worker class, and made up some functions/delegates to handle the
>>> invoke stuff for the UI and that was fine for a prototype. I rewrote
>>> this chunk, broke things out into different classes - but the threading
>>> is still the same - and one specific problem I'm having is this.
>>>
>>> Within the worker thread, I do this:
>>>
>>> ListViewItem lvwItem = new ListViewItem();
>>>
>>> I want to try to do as much work as possible, while leaving a lot of
>>> potential functionality in the worker thread. So I'd like to
>>> pre-populate a ListViewItem - and then do the Invoke to just add that
>>> pre-filled ListViewItem to the listview on the UI.
>>>
>>> On that line, I get an error of:
>>>
>>> Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>> thread other than the thread it was created on.
>>> Stack trace where the illegal operation occurred was:
>>>
>>> at System.Windows.Forms.Control.get_Handle() etc, etc
>>>
>>> And it happens right at that line above when I'm trying to create a
>>> ListViewItem programatically. I am assuming that when you create a UI
>>> element programatically, it needs a window handle? If so - how do I get
>>> around this? And I know I've had this work before, the only thing
>>> different is I have this functionality in a seperate class.
>>>
>>> Also - I got rid of 100% of the functionality in that thread (commented
>>> it
>>> out) - and slowly added lines back in, and this is the only, even remote
>>> reference to a UI element in this chunk of code, and this is the
>>> specific line that throws the exception.
>>>
>>> Any ideas???[/color]
>>
>> --
>> Texeme
>> http://texeme.com
>>[/color][/color]

--
Texeme
http://texeme.com

Elidel
Guest
 
Posts: n/a
#6: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


RCS wrote:

[color=blue]
> System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
> LoadListView1 );
> System.Threading.Thread objThread = new System.Threading.Thread( objTS );
> objThread.Name = "LoadListView1";
> objThread.Start();
>
>
> Then, within that function, I am immediately doing this:
>
>
> ListViewItem lvwItem = new ListViewItem();[/color]

And you then get the error:

Control 'frmPopup' accessed from a thread ?

What does objTS look like ?

[color=blue]
>
>
> That is enough to make it fail. So, I'm not actually trying to update any
> UI elements on a form, at this point - I'm just programatically creating a
> UI element that will be added to one of my forms later.
>
>
>
> "Elidel" <im@elidel.l.eh.del> wrote in message
> news:rX8Nd.1166$UX3.1062@newsread3.news.pas.earthl ink.net...[color=green]
>>
>> I don't know how your creating your thread, but it sounds like the error
>> is
>> in how you pass back the result to the main ( calling ) thread.
>>
>> So, for example, if you try to add lvwItem to frmPopup in the spawned
>> thread
>> you might get that error.
>>
>> If you set up, say, a thread pool, that calls a method that returns
>> ListViewItem as a result, and then add it to frmPopup control array, that
>> might be different.
>>
>> RCS wrote:
>>[color=darkred]
>>>
>>> I have a UI that needs a couple of threads to do some significant
>>> processing on a couple of different forms - and while it's at it, update
>>> the UI (set textboxes, fill in listviews). I created a base class for
>>> the worker class, and made up some functions/delegates to handle the
>>> invoke stuff for the UI and that was fine for a prototype. I rewrote
>>> this chunk, broke things out into different classes - but the threading
>>> is still the same - and one specific problem I'm having is this.
>>>
>>> Within the worker thread, I do this:
>>>
>>> ListViewItem lvwItem = new ListViewItem();
>>>
>>> I want to try to do as much work as possible, while leaving a lot of
>>> potential functionality in the worker thread. So I'd like to
>>> pre-populate a ListViewItem - and then do the Invoke to just add that
>>> pre-filled ListViewItem to the listview on the UI.
>>>
>>> On that line, I get an error of:
>>>
>>> Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>> thread other than the thread it was created on.
>>> Stack trace where the illegal operation occurred was:
>>>
>>> at System.Windows.Forms.Control.get_Handle() etc, etc
>>>
>>> And it happens right at that line above when I'm trying to create a
>>> ListViewItem programatically. I am assuming that when you create a UI
>>> element programatically, it needs a window handle? If so - how do I get
>>> around this? And I know I've had this work before, the only thing
>>> different is I have this functionality in a seperate class.
>>>
>>> Also - I got rid of 100% of the functionality in that thread (commented
>>> it
>>> out) - and slowly added lines back in, and this is the only, even remote
>>> reference to a UI element in this chunk of code, and this is the
>>> specific line that throws the exception.
>>>
>>> Any ideas???[/color]
>>
>> --
>> Texeme
>> http://texeme.com
>>[/color][/color]

--
Texeme
http://texeme.com

Elidel
Guest
 
Posts: n/a
#7: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


Elidel wrote:

Or rather, what does LoadListView1 look like ?
[color=blue]
> RCS wrote:
>[color=green]
>> Windows doesn't allow a secondary thread to update any UI elements.[/color]
>
> I'm not saying it should.
>
> I'm saying you can return a new object -- which has the values you want,
> and then in the main thread, update the UI element with that value.
>
>[color=green]
>> You
>> have to have the original UI thread do that. So what you can do from the
>> secondary thread is:
>>
>> if ( InvokeRequired )
>> {
>> BeginInvoke(...)
>> }
>> // Do the real work here
>>
>>
>> That part of this, is all good and works fine. There is somewhat of a
>> detailed class that handles all the UI elements that I'd need to update
>> from a background thread. But way before I get to that, and to address
>> what you've asked. From the UI thread I do this to start things off:
>>
>>
>> System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
>> LoadListView1 );
>> System.Threading.Thread objThread = new System.Threading.Thread( objTS );
>> objThread.Name = "LoadListView1";
>> objThread.Start();
>>
>>
>> Then, within that function, I am immediately doing this:
>>
>>
>> ListViewItem lvwItem = new ListViewItem();
>>
>>
>> That is enough to make it fail. So, I'm not actually trying to update any
>> UI elements on a form, at this point - I'm just programatically creating
>> a UI element that will be added to one of my forms later.
>>
>>
>>
>> "Elidel" <im@elidel.l.eh.del> wrote in message
>> news:rX8Nd.1166$UX3.1062@newsread3.news.pas.earthl ink.net...[color=darkred]
>>>
>>> I don't know how your creating your thread, but it sounds like the error
>>> is
>>> in how you pass back the result to the main ( calling ) thread.
>>>
>>> So, for example, if you try to add lvwItem to frmPopup in the spawned
>>> thread
>>> you might get that error.
>>>
>>> If you set up, say, a thread pool, that calls a method that returns
>>> ListViewItem as a result, and then add it to frmPopup control array,
>>> that might be different.
>>>
>>> RCS wrote:
>>>
>>>>
>>>> I have a UI that needs a couple of threads to do some significant
>>>> processing on a couple of different forms - and while it's at it,
>>>> update the UI (set textboxes, fill in listviews). I created a base
>>>> class for the worker class, and made up some functions/delegates to
>>>> handle the invoke stuff for the UI and that was fine for a prototype. I
>>>> rewrote this chunk, broke things out into different classes - but the
>>>> threading is still the same - and one specific problem I'm having is
>>>> this.
>>>>
>>>> Within the worker thread, I do this:
>>>>
>>>> ListViewItem lvwItem = new ListViewItem();
>>>>
>>>> I want to try to do as much work as possible, while leaving a lot of
>>>> potential functionality in the worker thread. So I'd like to
>>>> pre-populate a ListViewItem - and then do the Invoke to just add that
>>>> pre-filled ListViewItem to the listview on the UI.
>>>>
>>>> On that line, I get an error of:
>>>>
>>>> Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>>> thread other than the thread it was created on.
>>>> Stack trace where the illegal operation occurred was:
>>>>
>>>> at System.Windows.Forms.Control.get_Handle() etc, etc
>>>>
>>>> And it happens right at that line above when I'm trying to create a
>>>> ListViewItem programatically. I am assuming that when you create a UI
>>>> element programatically, it needs a window handle? If so - how do I get
>>>> around this? And I know I've had this work before, the only thing
>>>> different is I have this functionality in a seperate class.
>>>>
>>>> Also - I got rid of 100% of the functionality in that thread (commented
>>>> it
>>>> out) - and slowly added lines back in, and this is the only, even
>>>> remote reference to a UI element in this chunk of code, and this is the
>>>> specific line that throws the exception.
>>>>
>>>> Any ideas???
>>>
>>> --
>>> Texeme
>>> http://texeme.com
>>>[/color][/color]
>[/color]

--
Texeme
http://texeme.com

RCS
Guest
 
Posts: n/a
#8: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


That's it - just one line in it:

ListViewItem lvwItem = new ListViewItem();


"Elidel" <im@elidel.l.eh.del> wrote in message
news:CX9Nd.1148$mG6.23@newsread1.news.pas.earthlin k.net...[color=blue]
> Elidel wrote:
>
> Or rather, what does LoadListView1 look like ?
>[color=green]
>> RCS wrote:
>>[color=darkred]
>>> Windows doesn't allow a secondary thread to update any UI elements.[/color]
>>
>> I'm not saying it should.
>>
>> I'm saying you can return a new object -- which has the values you want,
>> and then in the main thread, update the UI element with that value.
>>
>>[color=darkred]
>>> You
>>> have to have the original UI thread do that. So what you can do from the
>>> secondary thread is:
>>>
>>> if ( InvokeRequired )
>>> {
>>> BeginInvoke(...)
>>> }
>>> // Do the real work here
>>>
>>>
>>> That part of this, is all good and works fine. There is somewhat of a
>>> detailed class that handles all the UI elements that I'd need to update
>>> from a background thread. But way before I get to that, and to address
>>> what you've asked. From the UI thread I do this to start things off:
>>>
>>>
>>> System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
>>> LoadListView1 );
>>> System.Threading.Thread objThread = new System.Threading.Thread(
>>> objTS );
>>> objThread.Name = "LoadListView1";
>>> objThread.Start();
>>>
>>>
>>> Then, within that function, I am immediately doing this:
>>>
>>>
>>> ListViewItem lvwItem = new ListViewItem();
>>>
>>>
>>> That is enough to make it fail. So, I'm not actually trying to update
>>> any
>>> UI elements on a form, at this point - I'm just programatically creating
>>> a UI element that will be added to one of my forms later.
>>>
>>>
>>>
>>> "Elidel" <im@elidel.l.eh.del> wrote in message
>>> news:rX8Nd.1166$UX3.1062@newsread3.news.pas.earthl ink.net...
>>>>
>>>> I don't know how your creating your thread, but it sounds like the
>>>> error
>>>> is
>>>> in how you pass back the result to the main ( calling ) thread.
>>>>
>>>> So, for example, if you try to add lvwItem to frmPopup in the spawned
>>>> thread
>>>> you might get that error.
>>>>
>>>> If you set up, say, a thread pool, that calls a method that returns
>>>> ListViewItem as a result, and then add it to frmPopup control array,
>>>> that might be different.
>>>>
>>>> RCS wrote:
>>>>
>>>>>
>>>>> I have a UI that needs a couple of threads to do some significant
>>>>> processing on a couple of different forms - and while it's at it,
>>>>> update the UI (set textboxes, fill in listviews). I created a base
>>>>> class for the worker class, and made up some functions/delegates to
>>>>> handle the invoke stuff for the UI and that was fine for a prototype.
>>>>> I
>>>>> rewrote this chunk, broke things out into different classes - but the
>>>>> threading is still the same - and one specific problem I'm having is
>>>>> this.
>>>>>
>>>>> Within the worker thread, I do this:
>>>>>
>>>>> ListViewItem lvwItem = new ListViewItem();
>>>>>
>>>>> I want to try to do as much work as possible, while leaving a lot of
>>>>> potential functionality in the worker thread. So I'd like to
>>>>> pre-populate a ListViewItem - and then do the Invoke to just add that
>>>>> pre-filled ListViewItem to the listview on the UI.
>>>>>
>>>>> On that line, I get an error of:
>>>>>
>>>>> Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>>>> thread other than the thread it was created on.
>>>>> Stack trace where the illegal operation occurred was:
>>>>>
>>>>> at System.Windows.Forms.Control.get_Handle() etc, etc
>>>>>
>>>>> And it happens right at that line above when I'm trying to create a
>>>>> ListViewItem programatically. I am assuming that when you create a UI
>>>>> element programatically, it needs a window handle? If so - how do I
>>>>> get
>>>>> around this? And I know I've had this work before, the only thing
>>>>> different is I have this functionality in a seperate class.
>>>>>
>>>>> Also - I got rid of 100% of the functionality in that thread
>>>>> (commented
>>>>> it
>>>>> out) - and slowly added lines back in, and this is the only, even
>>>>> remote reference to a UI element in this chunk of code, and this is
>>>>> the
>>>>> specific line that throws the exception.
>>>>>
>>>>> Any ideas???
>>>>
>>>> --
>>>> Texeme
>>>> http://texeme.com
>>>>[/color]
>>[/color]
>
> --
> Texeme
> http://texeme.com
>[/color]


RCS
Guest
 
Posts: n/a
#9: Nov 16 '05

re: Threading with UI elements - dynamically created controls?



No no, that's a rule in Windows programming. You can't reference a loaded UI
object that was not created in your thread - you get a runtime error (this
is VS.NET 2K5 beta 1 by the way - I believe it was allowed in VS.NET 2K3)

"Elidel" <im@elidel.l.eh.del> wrote in message
news:QS9Nd.1143$mG6.1009@newsread1.news.pas.earthl ink.net...[color=blue]
> RCS wrote:
>[color=green]
>> Windows doesn't allow a secondary thread to update any UI elements.[/color]
>
> I'm not saying it should.
>
> I'm saying you can return a new object -- which has the values you want,
> and
> then in the main thread, update the UI element with that value.
>
>[color=green]
>> You
>> have to have the original UI thread do that. So what you can do from the
>> secondary thread is:
>>
>> if ( InvokeRequired )
>> {
>> BeginInvoke(...)
>> }
>> // Do the real work here
>>
>>
>> That part of this, is all good and works fine. There is somewhat of a
>> detailed class that handles all the UI elements that I'd need to update
>> from a background thread. But way before I get to that, and to address
>> what you've asked. From the UI thread I do this to start things off:
>>
>>
>> System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
>> LoadListView1 );
>> System.Threading.Thread objThread = new System.Threading.Thread( objTS );
>> objThread.Name = "LoadListView1";
>> objThread.Start();
>>
>>
>> Then, within that function, I am immediately doing this:
>>
>>
>> ListViewItem lvwItem = new ListViewItem();
>>
>>
>> That is enough to make it fail. So, I'm not actually trying to update any
>> UI elements on a form, at this point - I'm just programatically creating
>> a
>> UI element that will be added to one of my forms later.
>>
>>
>>
>> "Elidel" <im@elidel.l.eh.del> wrote in message
>> news:rX8Nd.1166$UX3.1062@newsread3.news.pas.earthl ink.net...[color=darkred]
>>>
>>> I don't know how your creating your thread, but it sounds like the error
>>> is
>>> in how you pass back the result to the main ( calling ) thread.
>>>
>>> So, for example, if you try to add lvwItem to frmPopup in the spawned
>>> thread
>>> you might get that error.
>>>
>>> If you set up, say, a thread pool, that calls a method that returns
>>> ListViewItem as a result, and then add it to frmPopup control array,
>>> that
>>> might be different.
>>>
>>> RCS wrote:
>>>
>>>>
>>>> I have a UI that needs a couple of threads to do some significant
>>>> processing on a couple of different forms - and while it's at it,
>>>> update
>>>> the UI (set textboxes, fill in listviews). I created a base class for
>>>> the worker class, and made up some functions/delegates to handle the
>>>> invoke stuff for the UI and that was fine for a prototype. I rewrote
>>>> this chunk, broke things out into different classes - but the threading
>>>> is still the same - and one specific problem I'm having is this.
>>>>
>>>> Within the worker thread, I do this:
>>>>
>>>> ListViewItem lvwItem = new ListViewItem();
>>>>
>>>> I want to try to do as much work as possible, while leaving a lot of
>>>> potential functionality in the worker thread. So I'd like to
>>>> pre-populate a ListViewItem - and then do the Invoke to just add that
>>>> pre-filled ListViewItem to the listview on the UI.
>>>>
>>>> On that line, I get an error of:
>>>>
>>>> Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>>> thread other than the thread it was created on.
>>>> Stack trace where the illegal operation occurred was:
>>>>
>>>> at System.Windows.Forms.Control.get_Handle() etc, etc
>>>>
>>>> And it happens right at that line above when I'm trying to create a
>>>> ListViewItem programatically. I am assuming that when you create a UI
>>>> element programatically, it needs a window handle? If so - how do I get
>>>> around this? And I know I've had this work before, the only thing
>>>> different is I have this functionality in a seperate class.
>>>>
>>>> Also - I got rid of 100% of the functionality in that thread (commented
>>>> it
>>>> out) - and slowly added lines back in, and this is the only, even
>>>> remote
>>>> reference to a UI element in this chunk of code, and this is the
>>>> specific line that throws the exception.
>>>>
>>>> Any ideas???
>>>
>>> --
>>> Texeme
>>> http://texeme.com
>>>[/color][/color]
>
> --
> Texeme
> http://texeme.com
>[/color]


Elidel
Guest
 
Posts: n/a
#10: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


RCS wrote:

So the idea is

1. Create a ListView0 in the main thread.
2. Spawn the thread, create the ListView1 with data.
3. Take the return value of the threaded method, and set

ListView0 = ListView1

[color=blue]
>
> No no, that's a rule in Windows programming. You can't reference a loaded
> UI object that was not created in your thread - you get a runtime error
> (this is VS.NET 2K5 beta 1 by the way - I believe it was allowed in VS.NET
> 2K3)
>
> "Elidel" <im@elidel.l.eh.del> wrote in message
> news:QS9Nd.1143$mG6.1009@newsread1.news.pas.earthl ink.net...[color=green]
>> RCS wrote:
>>[color=darkred]
>>> Windows doesn't allow a secondary thread to update any UI elements.[/color]
>>
>> I'm not saying it should.
>>
>> I'm saying you can return a new object -- which has the values you want,
>> and
>> then in the main thread, update the UI element with that value.
>>
>>[color=darkred]
>>> You
>>> have to have the original UI thread do that. So what you can do from the
>>> secondary thread is:
>>>
>>> if ( InvokeRequired )
>>> {
>>> BeginInvoke(...)
>>> }
>>> // Do the real work here
>>>
>>>
>>> That part of this, is all good and works fine. There is somewhat of a
>>> detailed class that handles all the UI elements that I'd need to update
>>> from a background thread. But way before I get to that, and to address
>>> what you've asked. From the UI thread I do this to start things off:
>>>
>>>
>>> System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
>>> LoadListView1 );
>>> System.Threading.Thread objThread = new System.Threading.Thread( objTS
>>> ); objThread.Name = "LoadListView1";
>>> objThread.Start();
>>>
>>>
>>> Then, within that function, I am immediately doing this:
>>>
>>>
>>> ListViewItem lvwItem = new ListViewItem();
>>>
>>>
>>> That is enough to make it fail. So, I'm not actually trying to update
>>> any UI elements on a form, at this point - I'm just programatically
>>> creating a
>>> UI element that will be added to one of my forms later.
>>>
>>>
>>>
>>> "Elidel" <im@elidel.l.eh.del> wrote in message
>>> news:rX8Nd.1166$UX3.1062@newsread3.news.pas.earthl ink.net...
>>>>
>>>> I don't know how your creating your thread, but it sounds like the
>>>> error is
>>>> in how you pass back the result to the main ( calling ) thread.
>>>>
>>>> So, for example, if you try to add lvwItem to frmPopup in the spawned
>>>> thread
>>>> you might get that error.
>>>>
>>>> If you set up, say, a thread pool, that calls a method that returns
>>>> ListViewItem as a result, and then add it to frmPopup control array,
>>>> that
>>>> might be different.
>>>>
>>>> RCS wrote:
>>>>
>>>>>
>>>>> I have a UI that needs a couple of threads to do some significant
>>>>> processing on a couple of different forms - and while it's at it,
>>>>> update
>>>>> the UI (set textboxes, fill in listviews). I created a base class for
>>>>> the worker class, and made up some functions/delegates to handle the
>>>>> invoke stuff for the UI and that was fine for a prototype. I rewrote
>>>>> this chunk, broke things out into different classes - but the
>>>>> threading is still the same - and one specific problem I'm having is
>>>>> this.
>>>>>
>>>>> Within the worker thread, I do this:
>>>>>
>>>>> ListViewItem lvwItem = new ListViewItem();
>>>>>
>>>>> I want to try to do as much work as possible, while leaving a lot of
>>>>> potential functionality in the worker thread. So I'd like to
>>>>> pre-populate a ListViewItem - and then do the Invoke to just add that
>>>>> pre-filled ListViewItem to the listview on the UI.
>>>>>
>>>>> On that line, I get an error of:
>>>>>
>>>>> Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>>>> thread other than the thread it was created on.
>>>>> Stack trace where the illegal operation occurred was:
>>>>>
>>>>> at System.Windows.Forms.Control.get_Handle() etc, etc
>>>>>
>>>>> And it happens right at that line above when I'm trying to create a
>>>>> ListViewItem programatically. I am assuming that when you create a UI
>>>>> element programatically, it needs a window handle? If so - how do I
>>>>> get around this? And I know I've had this work before, the only thing
>>>>> different is I have this functionality in a seperate class.
>>>>>
>>>>> Also - I got rid of 100% of the functionality in that thread
>>>>> (commented it
>>>>> out) - and slowly added lines back in, and this is the only, even
>>>>> remote
>>>>> reference to a UI element in this chunk of code, and this is the
>>>>> specific line that throws the exception.
>>>>>
>>>>> Any ideas???
>>>>
>>>> --
>>>> Texeme
>>>> http://texeme.com
>>>>[/color]
>>
>> --
>> Texeme
>> http://texeme.com
>>[/color][/color]

--
Texeme
http://texeme.com

RCS
Guest
 
Posts: n/a
#11: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


Well, I'd rather not do that, because there are a lot of screens and lot of
different UI elements - and I'd rather do it the proper way. Ideally:


UI Thread:
Draw the interface, create a listview, spawn a new thread that does
"something", then sit idle

Background Thread:
Dynamically create an unbound programatic ListViewItem (an item that is in a
ListView) - populate that, then BeginInvoke to the UI thread to have it add
the new row.


meanwhile, the idle UI thread gets a BeginInvoke to insert a new
ListViewItem.. a couple of these listviews update over time.. so
pre-loading them, then copying them would be bulky and messy. I want to be
able to do this one row at a time..

thanks


"Elidel" <im@elidel.l.eh.del> wrote in message
news:WJbNd.1275$UX3.1046@newsread3.news.pas.earthl ink.net...[color=blue]
> RCS wrote:
>
> So the idea is
>
> 1. Create a ListView0 in the main thread.
> 2. Spawn the thread, create the ListView1 with data.
> 3. Take the return value of the threaded method, and set
>
> ListView0 = ListView1
>
>[color=green]
>>
>> No no, that's a rule in Windows programming. You can't reference a loaded
>> UI object that was not created in your thread - you get a runtime error
>> (this is VS.NET 2K5 beta 1 by the way - I believe it was allowed in
>> VS.NET
>> 2K3)
>>
>> "Elidel" <im@elidel.l.eh.del> wrote in message
>> news:QS9Nd.1143$mG6.1009@newsread1.news.pas.earthl ink.net...[color=darkred]
>>> RCS wrote:
>>>
>>>> Windows doesn't allow a secondary thread to update any UI elements.
>>>
>>> I'm not saying it should.
>>>
>>> I'm saying you can return a new object -- which has the values you want,
>>> and
>>> then in the main thread, update the UI element with that value.
>>>
>>>
>>>> You
>>>> have to have the original UI thread do that. So what you can do from
>>>> the
>>>> secondary thread is:
>>>>
>>>> if ( InvokeRequired )
>>>> {
>>>> BeginInvoke(...)
>>>> }
>>>> // Do the real work here
>>>>
>>>>
>>>> That part of this, is all good and works fine. There is somewhat of a
>>>> detailed class that handles all the UI elements that I'd need to update
>>>> from a background thread. But way before I get to that, and to address
>>>> what you've asked. From the UI thread I do this to start things off:
>>>>
>>>>
>>>> System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
>>>> LoadListView1 );
>>>> System.Threading.Thread objThread = new System.Threading.Thread( objTS
>>>> ); objThread.Name = "LoadListView1";
>>>> objThread.Start();
>>>>
>>>>
>>>> Then, within that function, I am immediately doing this:
>>>>
>>>>
>>>> ListViewItem lvwItem = new ListViewItem();
>>>>
>>>>
>>>> That is enough to make it fail. So, I'm not actually trying to update
>>>> any UI elements on a form, at this point - I'm just programatically
>>>> creating a
>>>> UI element that will be added to one of my forms later.
>>>>
>>>>
>>>>
>>>> "Elidel" <im@elidel.l.eh.del> wrote in message
>>>> news:rX8Nd.1166$UX3.1062@newsread3.news.pas.earthl ink.net...
>>>>>
>>>>> I don't know how your creating your thread, but it sounds like the
>>>>> error is
>>>>> in how you pass back the result to the main ( calling ) thread.
>>>>>
>>>>> So, for example, if you try to add lvwItem to frmPopup in the spawned
>>>>> thread
>>>>> you might get that error.
>>>>>
>>>>> If you set up, say, a thread pool, that calls a method that returns
>>>>> ListViewItem as a result, and then add it to frmPopup control array,
>>>>> that
>>>>> might be different.
>>>>>
>>>>> RCS wrote:
>>>>>
>>>>>>
>>>>>> I have a UI that needs a couple of threads to do some significant
>>>>>> processing on a couple of different forms - and while it's at it,
>>>>>> update
>>>>>> the UI (set textboxes, fill in listviews). I created a base class for
>>>>>> the worker class, and made up some functions/delegates to handle the
>>>>>> invoke stuff for the UI and that was fine for a prototype. I rewrote
>>>>>> this chunk, broke things out into different classes - but the
>>>>>> threading is still the same - and one specific problem I'm having is
>>>>>> this.
>>>>>>
>>>>>> Within the worker thread, I do this:
>>>>>>
>>>>>> ListViewItem lvwItem = new ListViewItem();
>>>>>>
>>>>>> I want to try to do as much work as possible, while leaving a lot of
>>>>>> potential functionality in the worker thread. So I'd like to
>>>>>> pre-populate a ListViewItem - and then do the Invoke to just add that
>>>>>> pre-filled ListViewItem to the listview on the UI.
>>>>>>
>>>>>> On that line, I get an error of:
>>>>>>
>>>>>> Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>>>>> thread other than the thread it was created on.
>>>>>> Stack trace where the illegal operation occurred was:
>>>>>>
>>>>>> at System.Windows.Forms.Control.get_Handle() etc, etc
>>>>>>
>>>>>> And it happens right at that line above when I'm trying to create a
>>>>>> ListViewItem programatically. I am assuming that when you create a UI
>>>>>> element programatically, it needs a window handle? If so - how do I
>>>>>> get around this? And I know I've had this work before, the only thing
>>>>>> different is I have this functionality in a seperate class.
>>>>>>
>>>>>> Also - I got rid of 100% of the functionality in that thread
>>>>>> (commented it
>>>>>> out) - and slowly added lines back in, and this is the only, even
>>>>>> remote
>>>>>> reference to a UI element in this chunk of code, and this is the
>>>>>> specific line that throws the exception.
>>>>>>
>>>>>> Any ideas???
>>>>>
>>>>> --
>>>>> Texeme
>>>>> http://texeme.com
>>>>>
>>>
>>> --
>>> Texeme
>>> http://texeme.com
>>>[/color][/color]
>
> --
> Texeme
> http://texeme.com
>[/color]


Elidel
Guest
 
Posts: n/a
#12: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


RCS wrote:[color=blue]
> Well, I'd rather not do that, because there are a lot of screens and lot of
> different UI elements[/color]

Does this help:

http://www.codeguru.com/columns/VB/print.php/c6553/
Asynchronous Programming with Thread Pools

Listing 1: Multithreading with an existing thread in ThreadPool.

1: Private Sub Form1_Load(ByVal sender As System.Object, _
2: ByVal e As System.EventArgs) Handles MyBase.Load
3:
4: ListBox1.Items.Clear()
5: ThreadPool.QueueUserWorkItem(AddressOf Initialize)
6:
7: End Sub
8:
9: Private Elem As String
10: Private Sub Add()
11: ListBox1.Items.Add(Elem)
12: Application.DoEvents()
13: End Sub
14:
15: Private Sub Initialize(ByVal State As Object)
16: Dim I As Integer
17:
18: SyncLock ListBox1.GetType
19:
20: For I = 10000000 To 1 Step -1
21: Elem = I
22: ListBox1.Invoke(CType(AddressOf Add, MethodInvoker))
23: Next
24:
25: End SyncLock
26:
27: End Sub




- and I'd rather do it the proper way. Ideally:[color=blue]
>
>
> UI Thread:
> Draw the interface, create a listview, spawn a new thread that does
> "something", then sit idle
>
> Background Thread:
> Dynamically create an unbound programatic ListViewItem (an item that is in a
> ListView) - populate that, then BeginInvoke to the UI thread to have it add
> the new row.
>
>
> meanwhile, the idle UI thread gets a BeginInvoke to insert a new
> ListViewItem.. a couple of these listviews update over time.. so
> pre-loading them, then copying them would be bulky and messy. I want to be
> able to do this one row at a time..
>
> thanks
>
>
> "Elidel" <im@elidel.l.eh.del> wrote in message
> news:WJbNd.1275$UX3.1046@newsread3.news.pas.earthl ink.net...
>[color=green]
>>RCS wrote:
>>
>>So the idea is
>>
>>1. Create a ListView0 in the main thread.
>>2. Spawn the thread, create the ListView1 with data.
>>3. Take the return value of the threaded method, and set
>>
>>ListView0 = ListView1
>>
>>
>>[color=darkred]
>>>No no, that's a rule in Windows programming. You can't reference a loaded
>>>UI object that was not created in your thread - you get a runtime error
>>>(this is VS.NET 2K5 beta 1 by the way - I believe it was allowed in
>>>VS.NET
>>>2K3)
>>>
>>>"Elidel" <im@elidel.l.eh.del> wrote in message
>>>news:QS9Nd.1143$mG6.1009@newsread1.news.pas.ear thlink.net...
>>>
>>>>RCS wrote:
>>>>
>>>>
>>>>>Windows doesn't allow a secondary thread to update any UI elements.
>>>>
>>>>I'm not saying it should.
>>>>
>>>>I'm saying you can return a new object -- which has the values you want,
>>>>and
>>>>then in the main thread, update the UI element with that value.
>>>>
>>>>
>>>>
>>>>>You
>>>>>have to have the original UI thread do that. So what you can do from
>>>>>the
>>>>>secondary thread is:
>>>>>
>>>>>if ( InvokeRequired )
>>>>>{
>>>>> BeginInvoke(...)
>>>>>}
>>>>>// Do the real work here
>>>>>
>>>>>
>>>>>That part of this, is all good and works fine. There is somewhat of a
>>>>>detailed class that handles all the UI elements that I'd need to update
>>>>>from a background thread. But way before I get to that, and to address
>>>>>what you've asked. From the UI thread I do this to start things off:
>>>>>
>>>>>
>>>>>System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
>>>>>LoadListView1 );
>>>>>System.Threading.Thread objThread = new System.Threading.Thread( objTS
>>>>>); objThread.Name = "LoadListView1";
>>>>>objThread.Start();
>>>>>
>>>>>
>>>>>Then, within that function, I am immediately doing this:
>>>>>
>>>>>
>>>>>ListViewItem lvwItem = new ListViewItem();
>>>>>
>>>>>
>>>>>That is enough to make it fail. So, I'm not actually trying to update
>>>>>any UI elements on a form, at this point - I'm just programatically
>>>>>creating a
>>>>>UI element that will be added to one of my forms later.
>>>>>
>>>>>
>>>>>
>>>>>"Elidel" <im@elidel.l.eh.del> wrote in message
>>>>>news:rX8Nd.1166$UX3.1062@newsread3.news.pas.e arthlink.net...
>>>>>
>>>>>>I don't know how your creating your thread, but it sounds like the
>>>>>>error is
>>>>>>in how you pass back the result to the main ( calling ) thread.
>>>>>>
>>>>>>So, for example, if you try to add lvwItem to frmPopup in the spawned
>>>>>>thread
>>>>>>you might get that error.
>>>>>>
>>>>>>If you set up, say, a thread pool, that calls a method that returns
>>>>>>ListViewItem as a result, and then add it to frmPopup control array,
>>>>>>that
>>>>>>might be different.
>>>>>>
>>>>>>RCS wrote:
>>>>>>
>>>>>>
>>>>>>>I have a UI that needs a couple of threads to do some significant
>>>>>>>processing on a couple of different forms - and while it's at it,
>>>>>>>update
>>>>>>>the UI (set textboxes, fill in listviews). I created a base class for
>>>>>>>the worker class, and made up some functions/delegates to handle the
>>>>>>>invoke stuff for the UI and that was fine for a prototype. I rewrote
>>>>>>>this chunk, broke things out into different classes - but the
>>>>>>>threading is still the same - and one specific problem I'm having is
>>>>>>>this.
>>>>>>>
>>>>>>>Within the worker thread, I do this:
>>>>>>>
>>>>>>>ListViewItem lvwItem = new ListViewItem();
>>>>>>>
>>>>>>>I want to try to do as much work as possible, while leaving a lot of
>>>>>>>potential functionality in the worker thread. So I'd like to
>>>>>>>pre-populate a ListViewItem - and then do the Invoke to just add that
>>>>>>>pre-filled ListViewItem to the listview on the UI.
>>>>>>>
>>>>>>>On that line, I get an error of:
>>>>>>>
>>>>>>>Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>>>>>>thread other than the thread it was created on.
>>>>>>>Stack trace where the illegal operation occurred was:
>>>>>>>
>>>>>>>at System.Windows.Forms.Control.get_Handle() etc, etc
>>>>>>>
>>>>>>>And it happens right at that line above when I'm trying to create a
>>>>>>>ListViewItem programatically. I am assuming that when you create a UI
>>>>>>>element programatically, it needs a window handle? If so - how do I
>>>>>>>get around this? And I know I've had this work before, the only thing
>>>>>>>different is I have this functionality in a seperate class.
>>>>>>>
>>>>>>>Also - I got rid of 100% of the functionality in that thread
>>>>>>>(commented it
>>>>>>>out) - and slowly added lines back in, and this is the only, even
>>>>>>>remote
>>>>>>>reference to a UI element in this chunk of code, and this is the
>>>>>>>specific line that throws the exception.
>>>>>>>
>>>>>>>Any ideas???
>>>>>>
>>>>>>--
>>>>>>Texeme
>>>>>>http://texeme.com
>>>>>>
>>>>
>>>>--
>>>>Texeme
>>>>http://texeme.com
>>>>[/color]
>>
>>--
>>Texeme
>>http://texeme.com
>>[/color]
>
>
>[/color]
RCS
Guest
 
Posts: n/a
#13: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


Thanks for the help - this ended up being the VS.NET 2K5 beta 1 IDE messing
up - if I closed and re-opened the project, I get a different error, and it
still showed it was coming from the same line. That was not correct. I fixed
the error and all works fine.

I guess I shouldn't expect so much from a beta 1 product!!

"Elidel" <get.carter@wise.guy> wrote in message
news:FydNd.1316$UX3.932@newsread3.news.pas.earthli nk.net...[color=blue]
> RCS wrote:[color=green]
>> Well, I'd rather not do that, because there are a lot of screens and lot
>> of different UI elements[/color]
>
> Does this help:
>
> http://www.codeguru.com/columns/VB/print.php/c6553/
> Asynchronous Programming with Thread Pools
>
> Listing 1: Multithreading with an existing thread in ThreadPool.
>
> 1: Private Sub Form1_Load(ByVal sender As System.Object, _
> 2: ByVal e As System.EventArgs) Handles MyBase.Load
> 3:
> 4: ListBox1.Items.Clear()
> 5: ThreadPool.QueueUserWorkItem(AddressOf Initialize)
> 6:
> 7: End Sub
> 8:
> 9: Private Elem As String
> 10: Private Sub Add()
> 11: ListBox1.Items.Add(Elem)
> 12: Application.DoEvents()
> 13: End Sub
> 14:
> 15: Private Sub Initialize(ByVal State As Object)
> 16: Dim I As Integer
> 17:
> 18: SyncLock ListBox1.GetType
> 19:
> 20: For I = 10000000 To 1 Step -1
> 21: Elem = I
> 22: ListBox1.Invoke(CType(AddressOf Add, MethodInvoker))
> 23: Next
> 24:
> 25: End SyncLock
> 26:
> 27: End Sub
>
>
>
>
> - and I'd rather do it the proper way. Ideally:[color=green]
>>
>>
>> UI Thread:
>> Draw the interface, create a listview, spawn a new thread that does
>> "something", then sit idle
>>
>> Background Thread:
>> Dynamically create an unbound programatic ListViewItem (an item that is
>> in a ListView) - populate that, then BeginInvoke to the UI thread to have
>> it add the new row.
>>
>>
>> meanwhile, the idle UI thread gets a BeginInvoke to insert a new
>> ListViewItem.. a couple of these listviews update over time.. so
>> pre-loading them, then copying them would be bulky and messy. I want to
>> be able to do this one row at a time..
>>
>> thanks
>>
>>
>> "Elidel" <im@elidel.l.eh.del> wrote in message
>> news:WJbNd.1275$UX3.1046@newsread3.news.pas.earthl ink.net...
>>[color=darkred]
>>>RCS wrote:
>>>
>>>So the idea is
>>>
>>>1. Create a ListView0 in the main thread.
>>>2. Spawn the thread, create the ListView1 with data.
>>>3. Take the return value of the threaded method, and set
>>>
>>>ListView0 = ListView1
>>>
>>>
>>>
>>>>No no, that's a rule in Windows programming. You can't reference a
>>>>loaded
>>>>UI object that was not created in your thread - you get a runtime error
>>>>(this is VS.NET 2K5 beta 1 by the way - I believe it was allowed in
>>>>VS.NET
>>>>2K3)
>>>>
>>>>"Elidel" <im@elidel.l.eh.del> wrote in message
>>>>news:QS9Nd.1143$mG6.1009@newsread1.news.pas.ea rthlink.net...
>>>>
>>>>>RCS wrote:
>>>>>
>>>>>
>>>>>>Windows doesn't allow a secondary thread to update any UI elements.
>>>>>
>>>>>I'm not saying it should.
>>>>>
>>>>>I'm saying you can return a new object -- which has the values you
>>>>>want,
>>>>>and
>>>>>then in the main thread, update the UI element with that value.
>>>>>
>>>>>
>>>>>
>>>>>>You
>>>>>>have to have the original UI thread do that. So what you can do from
>>>>>>the
>>>>>>secondary thread is:
>>>>>>
>>>>>>if ( InvokeRequired )
>>>>>>{
>>>>>> BeginInvoke(...)
>>>>>>}
>>>>>>// Do the real work here
>>>>>>
>>>>>>
>>>>>>That part of this, is all good and works fine. There is somewhat of a
>>>>>>detailed class that handles all the UI elements that I'd need to
>>>>>>update
>>>>>>from a background thread. But way before I get to that, and to address
>>>>>>what you've asked. From the UI thread I do this to start things off:
>>>>>>
>>>>>>
>>>>>>System.Threading.ThreadStart objTS = new System.Threading.ThreadStart(
>>>>>>LoadListView1 );
>>>>>>System.Threading.Thread objThread = new System.Threading.Thread( objTS
>>>>>>); objThread.Name = "LoadListView1";
>>>>>>objThread.Start();
>>>>>>
>>>>>>
>>>>>>Then, within that function, I am immediately doing this:
>>>>>>
>>>>>>
>>>>>>ListViewItem lvwItem = new ListViewItem();
>>>>>>
>>>>>>
>>>>>>That is enough to make it fail. So, I'm not actually trying to update
>>>>>>any UI elements on a form, at this point - I'm just programatically
>>>>>>creating a
>>>>>>UI element that will be added to one of my forms later.
>>>>>>
>>>>>>
>>>>>>
>>>>>>"Elidel" <im@elidel.l.eh.del> wrote in message
>>>>>>news:rX8Nd.1166$UX3.1062@newsread3.news.pas. earthlink.net...
>>>>>>
>>>>>>>I don't know how your creating your thread, but it sounds like the
>>>>>>>error is
>>>>>>>in how you pass back the result to the main ( calling ) thread.
>>>>>>>
>>>>>>>So, for example, if you try to add lvwItem to frmPopup in the spawned
>>>>>>>thread
>>>>>>>you might get that error.
>>>>>>>
>>>>>>>If you set up, say, a thread pool, that calls a method that returns
>>>>>>>ListViewItem as a result, and then add it to frmPopup control array,
>>>>>>>that
>>>>>>>might be different.
>>>>>>>
>>>>>>>RCS wrote:
>>>>>>>
>>>>>>>
>>>>>>>>I have a UI that needs a couple of threads to do some significant
>>>>>>>>processing on a couple of different forms - and while it's at it,
>>>>>>>>update
>>>>>>>>the UI (set textboxes, fill in listviews). I created a base class
>>>>>>>>for
>>>>>>>>the worker class, and made up some functions/delegates to handle the
>>>>>>>>invoke stuff for the UI and that was fine for a prototype. I rewrote
>>>>>>>>this chunk, broke things out into different classes - but the
>>>>>>>>threading is still the same - and one specific problem I'm having is
>>>>>>>>this.
>>>>>>>>
>>>>>>>>Within the worker thread, I do this:
>>>>>>>>
>>>>>>>>ListViewItem lvwItem = new ListViewItem();
>>>>>>>>
>>>>>>>>I want to try to do as much work as possible, while leaving a lot of
>>>>>>>>potential functionality in the worker thread. So I'd like to
>>>>>>>>pre-populate a ListViewItem - and then do the Invoke to just add
>>>>>>>>that
>>>>>>>>pre-filled ListViewItem to the listview on the UI.
>>>>>>>>
>>>>>>>>On that line, I get an error of:
>>>>>>>>
>>>>>>>>Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>>>>>>>thread other than the thread it was created on.
>>>>>>>>Stack trace where the illegal operation occurred was:
>>>>>>>>
>>>>>>>>at System.Windows.Forms.Control.get_Handle() etc, etc
>>>>>>>>
>>>>>>>>And it happens right at that line above when I'm trying to create a
>>>>>>>>ListViewItem programatically. I am assuming that when you create a
>>>>>>>>UI
>>>>>>>>element programatically, it needs a window handle? If so - how do I
>>>>>>>>get around this? And I know I've had this work before, the only
>>>>>>>>thing
>>>>>>>>different is I have this functionality in a seperate class.
>>>>>>>>
>>>>>>>>Also - I got rid of 100% of the functionality in that thread
>>>>>>>>(commented it
>>>>>>>>out) - and slowly added lines back in, and this is the only, even
>>>>>>>>remote
>>>>>>>>reference to a UI element in this chunk of code, and this is the
>>>>>>>>specific line that throws the exception.
>>>>>>>>
>>>>>>>>Any ideas???
>>>>>>>
>>>>>>>--
>>>>>>>Texeme
>>>>>>>http://texeme.com
>>>>>>>
>>>>>
>>>>>--
>>>>>Texeme
>>>>>http://texeme.com
>>>>>
>>>
>>>--
>>>Texeme
>>>http://texeme.com
>>>[/color]
>>
>>[/color][/color]

INGSOC
Guest
 
Posts: n/a
#14: Nov 16 '05

re: Threading with UI elements - dynamically created controls?


RCS wrote:
[color=blue]
> Thanks for the help - this ended up being the VS.NET 2K5 beta 1 IDE
> messing up - if I closed and re-opened the project, I get a different
> error, and it still showed it was coming from the same line. That was not
> correct. I fixed the error and all works fine.[/color]

Rule one of support: make sure it's plugged in.

[color=blue]
>
> I guess I shouldn't expect so much from a beta 1 product!!
>
> "Elidel" <get.carter@wise.guy> wrote in message
> news:FydNd.1316$UX3.932@newsread3.news.pas.earthli nk.net...[color=green]
>> RCS wrote:[color=darkred]
>>> Well, I'd rather not do that, because there are a lot of screens and lot
>>> of different UI elements[/color]
>>
>> Does this help:
>>
>> http://www.codeguru.com/columns/VB/print.php/c6553/
>> Asynchronous Programming with Thread Pools
>>
>> Listing 1: Multithreading with an existing thread in ThreadPool.
>>
>> 1: Private Sub Form1_Load(ByVal sender As System.Object, _
>> 2: ByVal e As System.EventArgs) Handles MyBase.Load
>> 3:
>> 4: ListBox1.Items.Clear()
>> 5: ThreadPool.QueueUserWorkItem(AddressOf Initialize)
>> 6:
>> 7: End Sub
>> 8:
>> 9: Private Elem As String
>> 10: Private Sub Add()
>> 11: ListBox1.Items.Add(Elem)
>> 12: Application.DoEvents()
>> 13: End Sub
>> 14:
>> 15: Private Sub Initialize(ByVal State As Object)
>> 16: Dim I As Integer
>> 17:
>> 18: SyncLock ListBox1.GetType
>> 19:
>> 20: For I = 10000000 To 1 Step -1
>> 21: Elem = I
>> 22: ListBox1.Invoke(CType(AddressOf Add, MethodInvoker))
>> 23: Next
>> 24:
>> 25: End SyncLock
>> 26:
>> 27: End Sub
>>
>>
>>
>>
>> - and I'd rather do it the proper way. Ideally:[color=darkred]
>>>
>>>
>>> UI Thread:
>>> Draw the interface, create a listview, spawn a new thread that does
>>> "something", then sit idle
>>>
>>> Background Thread:
>>> Dynamically create an unbound programatic ListViewItem (an item that is
>>> in a ListView) - populate that, then BeginInvoke to the UI thread to
>>> have it add the new row.
>>>
>>>
>>> meanwhile, the idle UI thread gets a BeginInvoke to insert a new
>>> ListViewItem.. a couple of these listviews update over time.. so
>>> pre-loading them, then copying them would be bulky and messy. I want to
>>> be able to do this one row at a time..
>>>
>>> thanks
>>>
>>>
>>> "Elidel" <im@elidel.l.eh.del> wrote in message
>>> news:WJbNd.1275$UX3.1046@newsread3.news.pas.earthl ink.net...
>>>
>>>>RCS wrote:
>>>>
>>>>So the idea is
>>>>
>>>>1. Create a ListView0 in the main thread.
>>>>2. Spawn the thread, create the ListView1 with data.
>>>>3. Take the return value of the threaded method, and set
>>>>
>>>>ListView0 = ListView1
>>>>
>>>>
>>>>
>>>>>No no, that's a rule in Windows programming. You can't reference a
>>>>>loaded
>>>>>UI object that was not created in your thread - you get a runtime error
>>>>>(this is VS.NET 2K5 beta 1 by the way - I believe it was allowed in
>>>>>VS.NET
>>>>>2K3)
>>>>>
>>>>>"Elidel" <im@elidel.l.eh.del> wrote in message
>>>>>news:QS9Nd.1143$mG6.1009@newsread1.news.pas.e arthlink.net...
>>>>>
>>>>>>RCS wrote:
>>>>>>
>>>>>>
>>>>>>>Windows doesn't allow a secondary thread to update any UI elements.
>>>>>>
>>>>>>I'm not saying it should.
>>>>>>
>>>>>>I'm saying you can return a new object -- which has the values you
>>>>>>want,
>>>>>>and
>>>>>>then in the main thread, update the UI element with that value.
>>>>>>
>>>>>>
>>>>>>
>>>>>>>You
>>>>>>>have to have the original UI thread do that. So what you can do from
>>>>>>>the
>>>>>>>secondary thread is:
>>>>>>>
>>>>>>>if ( InvokeRequired )
>>>>>>>{
>>>>>>> BeginInvoke(...)
>>>>>>>}
>>>>>>>// Do the real work here
>>>>>>>
>>>>>>>
>>>>>>>That part of this, is all good and works fine. There is somewhat of a
>>>>>>>detailed class that handles all the UI elements that I'd need to
>>>>>>>update
>>>>>>>from a background thread. But way before I get to that, and to
>>>>>>>address what you've asked. From the UI thread I do this to start
>>>>>>>things off:
>>>>>>>
>>>>>>>
>>>>>>>System.Threading.ThreadStart objTS = new
>>>>>>>System.Threading.ThreadStart( LoadListView1 );
>>>>>>>System.Threading.Thread objThread = new System.Threading.Thread(
>>>>>>>objTS ); objThread.Name = "LoadListView1";
>>>>>>>objThread.Start();
>>>>>>>
>>>>>>>
>>>>>>>Then, within that function, I am immediately doing this:
>>>>>>>
>>>>>>>
>>>>>>>ListViewItem lvwItem = new ListViewItem();
>>>>>>>
>>>>>>>
>>>>>>>That is enough to make it fail. So, I'm not actually trying to update
>>>>>>>any UI elements on a form, at this point - I'm just programatically
>>>>>>>creating a
>>>>>>>UI element that will be added to one of my forms later.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>"Elidel" <im@elidel.l.eh.del> wrote in message
>>>>>>>news:rX8Nd.1166$UX3.1062@newsread3.news.pas .earthlink.net...
>>>>>>>
>>>>>>>>I don't know how your creating your thread, but it sounds like the
>>>>>>>>error is
>>>>>>>>in how you pass back the result to the main ( calling ) thread.
>>>>>>>>
>>>>>>>>So, for example, if you try to add lvwItem to frmPopup in the
>>>>>>>>spawned thread
>>>>>>>>you might get that error.
>>>>>>>>
>>>>>>>>If you set up, say, a thread pool, that calls a method that returns
>>>>>>>>ListViewItem as a result, and then add it to frmPopup control array,
>>>>>>>>that
>>>>>>>>might be different.
>>>>>>>>
>>>>>>>>RCS wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>>I have a UI that needs a couple of threads to do some significant
>>>>>>>>>processing on a couple of different forms - and while it's at it,
>>>>>>>>>update
>>>>>>>>>the UI (set textboxes, fill in listviews). I created a base class
>>>>>>>>>for
>>>>>>>>>the worker class, and made up some functions/delegates to handle
>>>>>>>>>the invoke stuff for the UI and that was fine for a prototype. I
>>>>>>>>>rewrote this chunk, broke things out into different classes - but
>>>>>>>>>the threading is still the same - and one specific problem I'm
>>>>>>>>>having is this.
>>>>>>>>>
>>>>>>>>>Within the worker thread, I do this:
>>>>>>>>>
>>>>>>>>>ListViewItem lvwItem = new ListViewItem();
>>>>>>>>>
>>>>>>>>>I want to try to do as much work as possible, while leaving a lot
>>>>>>>>>of potential functionality in the worker thread. So I'd like to
>>>>>>>>>pre-populate a ListViewItem - and then do the Invoke to just add
>>>>>>>>>that
>>>>>>>>>pre-filled ListViewItem to the listview on the UI.
>>>>>>>>>
>>>>>>>>>On that line, I get an error of:
>>>>>>>>>
>>>>>>>>>Illegal cross-thread operation: Control 'frmPopup' accessed from a
>>>>>>>>>thread other than the thread it was created on.
>>>>>>>>>Stack trace where the illegal operation occurred was:
>>>>>>>>>
>>>>>>>>>at System.Windows.Forms.Control.get_Handle() etc, etc
>>>>>>>>>
>>>>>>>>>And it happens right at that line above when I'm trying to create a
>>>>>>>>>ListViewItem programatically. I am assuming that when you create a
>>>>>>>>>UI
>>>>>>>>>element programatically, it needs a window handle? If so - how do I
>>>>>>>>>get around this? And I know I've had this work before, the only
>>>>>>>>>thing
>>>>>>>>>different is I have this functionality in a seperate class.
>>>>>>>>>
>>>>>>>>>Also - I got rid of 100% of the functionality in that thread
>>>>>>>>>(commented it
>>>>>>>>>out) - and slowly added lines back in, and this is the only, even
>>>>>>>>>remote
>>>>>>>>>reference to a UI element in this chunk of code, and this is the
>>>>>>>>>specific line that throws the exception.
>>>>>>>>>
>>>>>>>>>Any ideas???
>>>>>>>>
>>>>>>>>--
>>>>>>>>Texeme
>>>>>>>>http://texeme.com
>>>>>>>>
>>>>>>
>>>>>>--
>>>>>>Texeme
>>>>>>http://texeme.com
>>>>>>
>>>>
>>>>--
>>>>Texeme
>>>>http://texeme.com
>>>>
>>>
>>>[/color][/color][/color]

--
Texeme
http://texeme.com

Closed Thread