Click here to Skip to main content
14,880,288 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
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:
C#
{
....
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:
C#
{
....
this.SetControlEnabled(btnPress, true);
...
}

and it does the job.

Can anyone help me with the menu item here?

Thank You,
-Bhaskar
Posted
Updated 18-Feb-11 5:07am
v3
Comments
Sergey Alexandrovich Kryukov 18-Feb-11 10:04am
   
Good question, my 5
--SA
Sandeep Mewara 18-Feb-11 10:34am
   
Format your code part in PRE tags. It makes the question readable.
Henry Minute 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

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 <code>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
   
v2
Comments
Sergey Alexandrovich Kryukov 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
Sergey Alexandrovich Kryukov 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
Sergey Alexandrovich Kryukov 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
Nish Nishant 18-Feb-11 10:22am
   
Good response, voted 5.
Sergey Alexandrovich Kryukov 18-Feb-11 10:27am
   
Thank you, still struggling through explaining to OP what to do.
--SA
Manfred Rudolf Bihy 18-Feb-11 10:54am
   
Good answer and follow up! 5+
Sergey Alexandrovich Kryukov 18-Feb-11 12:15pm
   
Thank you, Manfred,
--SA
Henry Minute 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
Sergey Alexandrovich Kryukov 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
Sergey Alexandrovich Kryukov 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)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900