The good old Cross-thread operation not valid

  • Thread starter Thread starter batvanio
  • Start date Start date
B

batvanio

Hi,

Does anyone know if there is a better solution for the good old
"Cross-thread operation not valid" than dealing with delegates and
Invokes? (This happens when you access GUI from a thread that did not
create it)

I realize that the problem is based on the old Windows requirement
(only thread that created the window shalt process its messages) but it
is 21 century and the new VS 2005 was supposed to be all about
productivity, concentrate on your buisness logic and do not write
plumbing code etc... If poluting your code with delegates and Invokes
just to do (txtBox1.Text = "Blah") is not plumbing I am not sure what
is....

Anyway, does anyone know if a better, more straightforward solution
exist? I guess the anonimous methods help a bit but it is still pretty
ugly. I also read about the BackgroudWorker component but that one is
not very intuitive either...

Ivan
 
This is pretty darn easy:

this.BeginInvoke(
(MethodInvoker)delegate()
{
this.progressBar1.Value = 100;
});

I think anyway you go, it would require a delegate so not sure how much more
they could simplify it.

--
William Stacey [MVP]

| Hi,
|
| Does anyone know if there is a better solution for the good old
| "Cross-thread operation not valid" than dealing with delegates and
| Invokes? (This happens when you access GUI from a thread that did not
| create it)
|
| I realize that the problem is based on the old Windows requirement
| (only thread that created the window shalt process its messages) but it
| is 21 century and the new VS 2005 was supposed to be all about
| productivity, concentrate on your buisness logic and do not write
| plumbing code etc... If poluting your code with delegates and Invokes
| just to do (txtBox1.Text = "Blah") is not plumbing I am not sure what
| is....
|
| Anyway, does anyone know if a better, more straightforward solution
| exist? I guess the anonimous methods help a bit but it is still pretty
| ugly. I also read about the BackgroudWorker component but that one is
| not very intuitive either...
|
| Ivan
|
 
Hi,

Apart from using Delegates approach, there is one more way to do this
if you are using Windows application.

In the Windows Form's constructor write this line of code:

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

Cheers!!
Dips
 
This does not solve the problem, it only hides the runtime error
message "cross-thread operation not valid"
The underlying issue is still there. I don't even know why MS
implemented this property - it only promotes bad practices...

Ivan
 
Thanks, William

This approach is a little more straightforward - at least no needs to
declare delegates.
I still believe a well-designed framework should take care of issues
like this behind the scenes, more transparently.

this.progressBar1.Value = 100 or something like

[CrossThreadedCall]
this.progressBar1.Value = 100

still look much cleaner than

this.BeginInvoke(
(MethodInvoker)delegate()
{
this.progressBar1.Value = 100;
});


Cheers,
Ivan
 
Also, the MethodInvoker for a void method that takes no prarams, so you
cannot pass info when updating the GUI, which is what you need most of
the time.
Probably there is another useful (and generic enough) delegate (taking
parameters and returning value) already declared in the framework that
I could use instead MethodInvoker?

Thanks
Ivan
 
Or maybe some like:

InvokeOnForm()
{
this.tb.Text = "hello";
this.progressBar.Value = 100;
}

This would be sugar to create the anonymous method and invoke it. Still,
the only thing your really saving is having to type
"(MethodInvoker)delegate()" - but it does look cleaner.

--
William Stacey [MVP]

| Thanks, William
|
| This approach is a little more straightforward - at least no needs to
| declare delegates.
| I still believe a well-designed framework should take care of issues
| like this behind the scenes, more transparently.
|
| this.progressBar1.Value = 100 or something like
|
| [CrossThreadedCall]
| this.progressBar1.Value = 100
|
| still look much cleaner than
|
| this.BeginInvoke(
| (MethodInvoker)delegate()
| {
| this.progressBar1.Value = 100;
| });
|
|
| Cheers,
| Ivan
|
| William Stacey [MVP] wrote:
| > This is pretty darn easy:
| >
| > this.BeginInvoke(
| > (MethodInvoker)delegate()
| > {
| > this.progressBar1.Value = 100;
| > });
| >
| > I think anyway you go, it would require a delegate so not sure how much
more
| > they could simplify it.
| >
| > --
| > William Stacey [MVP]
| >
| > | > | Hi,
| > |
| > | Does anyone know if there is a better solution for the good old
| > | "Cross-thread operation not valid" than dealing with delegates and
| > | Invokes? (This happens when you access GUI from a thread that did not
| > | create it)
| > |
| > | I realize that the problem is based on the old Windows requirement
| > | (only thread that created the window shalt process its messages) but
it
| > | is 21 century and the new VS 2005 was supposed to be all about
| > | productivity, concentrate on your buisness logic and do not write
| > | plumbing code etc... If poluting your code with delegates and Invokes
| > | just to do (txtBox1.Text = "Blah") is not plumbing I am not sure what
| > | is....
| > |
| > | Anyway, does anyone know if a better, more straightforward solution
| > | exist? I guess the anonimous methods help a bit but it is still pretty
| > | ugly. I also read about the BackgroudWorker component but that one is
| > | not very intuitive either...
| > |
| > | Ivan
| > |
|
 
But with local variable capture (inside the anonymous delegate), you don't
need to pass parms, just reference the vars you need. Or are you thinking
of something else? What is the issue?

--
William Stacey [MVP]

| Also, the MethodInvoker for a void method that takes no prarams, so you
| cannot pass info when updating the GUI, which is what you need most of
| the time.
| Probably there is another useful (and generic enough) delegate (taking
| parameters and returning value) already declared in the framework that
| I could use instead MethodInvoker?
|
| Thanks
| Ivan
|
| William Stacey [MVP] wrote:
| > This is pretty darn easy:
| >
| > this.BeginInvoke(
| > (MethodInvoker)delegate()
| > {
| > this.progressBar1.Value = 100;
| > });
| >
| > I think anyway you go, it would require a delegate so not sure how much
more
| > they could simplify it.
| >
| > --
| > William Stacey [MVP]
| >
| > | > | Hi,
| > |
| > | Does anyone know if there is a better solution for the good old
| > | "Cross-thread operation not valid" than dealing with delegates and
| > | Invokes? (This happens when you access GUI from a thread that did not
| > | create it)
| > |
| > | I realize that the problem is based on the old Windows requirement
| > | (only thread that created the window shalt process its messages) but
it
| > | is 21 century and the new VS 2005 was supposed to be all about
| > | productivity, concentrate on your buisness logic and do not write
| > | plumbing code etc... If poluting your code with delegates and Invokes
| > | just to do (txtBox1.Text = "Blah") is not plumbing I am not sure what
| > | is....
| > |
| > | Anyway, does anyone know if a better, more straightforward solution
| > | exist? I guess the anonimous methods help a bit but it is still pretty
| > | ugly. I also read about the BackgroudWorker component but that one is
| > | not very intuitive either...
| > |
| > | Ivan
| > |
|
 
I should add that if you needed to pass a parm, you can - just use a
different delegate type such as:
this.BeginInvoke(
(ParameterizedThreadStart)delegate(object o)
{
int i = (int)o;
Console.WriteLine("Hello." + i);
}, 3);

--
William Stacey [MVP]

| But with local variable capture (inside the anonymous delegate), you don't
| need to pass parms, just reference the vars you need. Or are you thinking
| of something else? What is the issue?
|
| --
| William Stacey [MVP]
|
| || Also, the MethodInvoker for a void method that takes no prarams, so you
|| cannot pass info when updating the GUI, which is what you need most of
|| the time.
|| Probably there is another useful (and generic enough) delegate (taking
|| parameters and returning value) already declared in the framework that
|| I could use instead MethodInvoker?
||
|| Thanks
|| Ivan
||
|| William Stacey [MVP] wrote:
|| > This is pretty darn easy:
|| >
|| > this.BeginInvoke(
|| > (MethodInvoker)delegate()
|| > {
|| > this.progressBar1.Value = 100;
|| > });
|| >
|| > I think anyway you go, it would require a delegate so not sure how much
| more
|| > they could simplify it.
|| >
|| > --
|| > William Stacey [MVP]
|| >
|| > || > | Hi,
|| > |
|| > | Does anyone know if there is a better solution for the good old
|| > | "Cross-thread operation not valid" than dealing with delegates and
|| > | Invokes? (This happens when you access GUI from a thread that did not
|| > | create it)
|| > |
|| > | I realize that the problem is based on the old Windows requirement
|| > | (only thread that created the window shalt process its messages) but
| it
|| > | is 21 century and the new VS 2005 was supposed to be all about
|| > | productivity, concentrate on your buisness logic and do not write
|| > | plumbing code etc... If poluting your code with delegates and Invokes
|| > | just to do (txtBox1.Text = "Blah") is not plumbing I am not sure what
|| > | is....
|| > |
|| > | Anyway, does anyone know if a better, more straightforward solution
|| > | exist? I guess the anonimous methods help a bit but it is still
pretty
|| > | ugly. I also read about the BackgroudWorker component but that one is
|| > | not very intuitive either...
|| > |
|| > | Ivan
|| > |
||
|
|
 
Back
Top