7

I am using the following code to invoke the controls that are on the main UI thread in my application. The progress bar that I have in my Status Strip does not have a InvokeRequired, I need to somehow invoke the System.Windows.Forms.ToolStripProgressBar.

if (txtbox1.InvokeRequired)
{
txtbox1.Invoke(new MethodInvoker(delegate { txtbox1.Text = string.Empty; }));
}
Sev
  • 761
  • 4
  • 16
  • 29
  • 1
    @Sev: If you are using System.Windows.Forms.Controls.ProgressBar then it contains InvokeRequeired method, because it is derived from Control and Control implements ISynchronizeInvoke interface. – Jalal Said Jun 28 '11 at 00:48
  • I am using System.Windows.Forms.ToolStripProgressBar – Sev Jun 28 '11 at 00:50
  • can I use a backgroundWorker just for this single control? I dont wanna redo the whole Threading codes – Sev Jun 28 '11 at 00:52
  • @Sev: it is not a Control. did you try using it and find any problems in multithread with it? – Jalal Said Jun 28 '11 at 00:53
  • it does not have a InvokeRequired, all other controls have InvokeRequired – Sev Jun 28 '11 at 00:55
  • @Sev: The `System.Windows.Forms.ToolStripProgressBar` is not inherited from `System.Windows.Forms.Control`, so it is not a control. the question is did you find any troubles when using it at multithreading application? – Jalal Said Jun 28 '11 at 00:58
  • yes, Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on. at System.Windows.Forms.Control.get_Handle() at System.Windows.Forms.Control.SendMessage(Int32 msg, Int32 wparam, Int32 lparam) at System.Windows.Forms.ProgressBar.UpdatePos() at System.Windows.Forms.ProgressBar.set_Value(Int32 value) at System.Windows.Forms.ToolStripProgressBar.set_Value(Int32 value) – Sev Jun 28 '11 at 01:01
  • 1
    @Sev: then use `this.InvokeRequired` because the `ToolStripProgressBar` and all other controls created in the form are created and initialized at the same form thread. – Jalal Said Jun 28 '11 at 01:04
  • this.InvokeRequired did not work, I tried the toolstrip.InvokeRequired too but no luck. – Sev Jun 28 '11 at 01:14
  • 1
    System.Windows.Forms.ToolStripProgressBarprgBarMain.GetCurrentParent().InvokeRequired is the solution in case someone needed – Sev Jun 28 '11 at 01:24

4 Answers4

8

Try

if (toolStripProgressBar1.Parent.InvokeRequired)
{
    toolStripProgressBar1.Parent.Invoke(new MethodInvoker(delegate { toolStripProgressBar1.Value= 100; }));
}
Bala R
  • 107,317
  • 23
  • 199
  • 210
  • 4
    Thank you but There is no Parent. instead I did this prgBarMain.GetCurrentParent().InvokeRequired – Sev Jun 28 '11 at 01:22
  • 1
    `Parent` is listed under Properties for `ToolStringProgressBar` http://msdn.microsoft.com/en-us/library/system.windows.forms.toolstripprogressbar.aspx . Not sure why you don't have it. – Bala R Jun 28 '11 at 01:25
  • 4
    Parent property is internal for .net 4.5 – Ronnie Overby Mar 22 '13 at 13:37
3

Try dropping in this handy extension method:

public static class ControlEx
{
    public static void Invoke(this System.Windows.Forms.Control @this, Action action)
    {
        if (@this == null) throw new ArgumentNullException("@this");
        if (action == null) throw new ArgumentNullException("action");
        if (@this.InvokeRequired)
        {
            @this.Invoke(action);
        }
        else
        {
            action();
        }
    }
}

Now you can just do this:

txtbox1.Invoke(() => toolStripProgressBar1.Value = value);

It safely calls the action on the UI thread and can be called from any actual control.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
2

Try invoking the ToolStrip and not the ToolStripProgressBar:

    delegate void ToolStripPrograssDelegate(int value);
    private void ToolStripPrograss(int value)
    {
        if (toolStrip1.InvokeRequired)
        {
            ToolStripPrograssDelegate del = new ToolStripPrograssDelegate(ToolStripPrograss);
            toolStrip1.Invoke(del, new object[] { value });
        }
        else
        {
            toolStripProgressBar1.Value = value; // Your thingy with the progress bar..
        }
    }

I'm not sure it will work, but give it a shoot.

If this wont work try this:

    delegate void ToolStripPrograssDelegate(int value);
    private void ToolStripPrograss(int value)
    {
        if (this.InvokeRequired)
        {
            ToolStripPrograssDelegate del = new ToolStripPrograssDelegate(ToolStripPrograss);
            this.Invoke(del, new object[] { value });
        }
        else
        {
            toolStripProgressBar1.Value = value; // Your thingy with the progress bar..
        }
    }

'this' should be the Form it's self.

WorkSmarter
  • 3,738
  • 3
  • 29
  • 34
Danpe
  • 18,668
  • 21
  • 96
  • 131
  • I am adding the steps to progressbar in the following method. How can I use your code here? public void AddProgressBarValue(int _step) { prgBarMain.Value += _step; } – Sev Jun 28 '11 at 01:07
1

You can alter the generic invoker from Automating the InvokeRequired code pattern designed to invoke any Control:

//Neat generic trick to invoke anything on a windows form control class  
//https://stackoverflow.com/questions/2367718/automating-the-invokerequired-code-pattern
//Use like this:
//object1.InvokeIfRequired(c => { c.Visible = true; });
//object1.InvokeIfRequired(c => { c.Text = "ABC"; });
//object1.InvokeIfRequired(c => 
//  { 
//      c.Text = "ABC";
//      c.Visible = true; 
//  }
//);
public static void InvokeIfRequired<T>(this T c, Action<T> action) where T : Control
{
    if (c.InvokeRequired)
    {
        c.Invoke(new Action(() => action(c)));
    }
    else
    {
        action(c);
    }
}

Objects in the ToolStrip are ToolStripItem and have no InvokeRequired. But the parent has and the above can be rewritten to use the parent .Invoke():

public static void InvokeIfRequiredToolstrip<T>(this T c, Action<T> action) where T : ToolStripItem
{
    if (c.GetCurrentParent().InvokeRequired)
    {
        c.GetCurrentParent().Invoke(new Action(() => action(c)));
    }
    else
    {
        action(c);
    }
}
flodis
  • 1,123
  • 13
  • 9