Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#2.0
Hi,
 
I am trying to change a menu item from another thread. I am able to use the InvokeRequired/Invoke on other controls, but since the menu item is not a Control, I am having difficulty in achieving the same functionality.
 
For other controls, I am doing this:
{
....
private delegate void SetControlEnableHandler(object sender, Boolean bValue);
 
private void SetControlEnabled(object sender, Boolean bValue)
        {
            Control control = (Control)sender;
            if (control.InvokeRequired)
            {
                control.Invoke(new SetControlEnableHandler(SetControlEnabled), new object[] { sender, bValue });
            }
            else
            {
                control.Enabled = bValue;
            }           
        }
....
}
From the worker thread I simple call:
{
....
this.SetControlEnabled(btnPress, true);
...
}
and it does the job.
 
Can anyone help me with the menu item here?
 
Thank You,
-Bhaskar
Posted 18-Feb-11 4:01am
Edited 18-Feb-11 5:07am
Henry Minute223.6K
v3
Comments
SAKryukov at 18-Feb-11 10:04am
   
Good question, my 5
--SA
Sandeep Mewara at 18-Feb-11 10:34am
   
Format your code part in PRE tags. It makes the question readable.
Henry Minute at 18-Feb-11 11:12am
   
When you want to respond to an answer, please use the 'Add comment' widget (bottom right of the answer) the answerer will then get an eMail notification. If you add an answer no one gets notified.
 
If you want to respond to a comment, hover your mouse over that comment and the 'Reply' widget will pop up. Simply click it.
 
:) :)

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Here is what you need to do: use InvokeRequired and Invoke of some other controls, first of all, of your form. It will work correctly!
 
Also, consider using BeginInvoke instead. If you're sure that your invocation call is always from non-UI thread, you may want to skip InvokeRequired check and always use Invoke or InvokeRequired.
 
Please see all the detail in my other Answer: Control.Invoke() vs. Control.BeginInvoke()[^].
 
Now, I'll explain why it does not matter which control is used for calling the invocation methods. The invocation mechanism works at the level of Application and the thread running Application.Run usually called UI thread. The mechanism is described in the referenced document and further references and based on the queue. The only requirement for the Control instance which instance method is used for invocation is being a part of the same Application which is usually the case unless you try very risky tricks with threads and Forms.
 
—SA
  Permalink  
v2
Comments
SAKryukov at 18-Feb-11 10:17am
   
OP commented:
 
Hi SAKryukov,
 
Thanks for your reply.
 
I am not sure what exactly you mean by using InvokeRequired and Invoke of some other control.
 
Can you please give an example?
 
Thank You,
-Bhaskar
SAKryukov at 18-Feb-11 10:20am
   
Bhaskar,
 
Let's assume your posted code is in the methods of some form. The form is also a Control (a derived class of Control), so it also has invocation methods. Use them!
 
Instead of "control.Invoke" (probably it will not even compile, right?) write "this.Invoke", "this.InvokeRequired" or "this.BeginInvoke". This works, I'll guarantee that. Read my big other answer referenced, the mechanism is explained.
 
Is that clear now?
 
--SA
SAKryukov at 18-Feb-11 10:26am
   
Yes, your code will compile but will throw exception by the reason you explained yourself.
"Control control = (Control)sender" will throw cast exception, because, as you explained, this sender is a menu item, which is not a control. Delete this line and replace "control" with "this". I hope "this" is your form, so it will work.
 
--SA
Nishant Sivakumar at 18-Feb-11 10:22am
   
Good response, voted 5.
SAKryukov at 18-Feb-11 10:27am
   
Thank you, still struggling through explaining to OP what to do.
--SA
Manfred R. Bihy at 18-Feb-11 10:54am
   
Good answer and follow up! 5+
SAKryukov at 18-Feb-11 12:15pm
   
Thank you, Manfred,
--SA
Henry Minute at 18-Feb-11 11:09am
   
From the OP - posted as an answer.
Hey,
 
I followed your advice. I did this, and it worked!
 
private delegate void SetMenuItemEnableHandler(object sender, Boolean bValue);
 
private void SetMenuItemEnabled(object sender, Boolean bValue)
{
ToolStripMenuItem menuStripItem = (ToolStripMenuItem)sender;
if (this.InvokeRequired)
{
this.Invoke(new SetMenuItemEnableHandler(SetMenuItemEnabled), new object[] { sender, bValue });
}
else
{
menuStripItem.Enabled = bValue;
}
}
 
From another thread I call this:
 
this.SetMenuItemEnabled(connectMenuItem, false);
 

Thanks a ton for your suggestion! I appreciate it.
 
I will follow your advice on using BeginInvoke too.
 
Have a great day ahead!
-Bhaskar
SAKryukov at 18-Feb-11 11:26am
   
Henry, thanks a lot for your help in organizing that; for OP, I already gave my notice of proper use of Questions below.
--SA
SAKryukov at 18-Feb-11 11:25am
   
Bhaskar,
 
First of all, thanks for understanding and accepting my answer.
 
Please, next time don't post non-answers as Answers. (See, they are deleted...) Instead, use "Improve question" or "Add comment". If you keep posting like that, no one will receive e-mail confirmation. (In this case Henry decided to help us to organize that properly.)
 
Also, please scan my recent Answers to other Questions (clicking in my Profile, and Answers) and review my other recent Answers on threading topics; it may save you from further problems with threading. If you still face them, you're welcome to call again.
 
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 6,651
1 Sergey Alexandrovich Kryukov 6,400
2 CPallini 5,230
3 George Jonsson 3,574
4 Gihan Liyanage 2,542


Advertise | Privacy | Mobile
Web01 | 2.8.140921.1 | Last Updated 18 Feb 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100