smoth190
smoth190

Reputation: 438

How do I set a ToolStripProgressBar's Value from a Thread?

Now, I know when most people see this kind of question, they think "Oh use delegates". Well, I am using delegates. And this is the only control so far that refuses to work with them. I am also not using the BackgroundWorker.

I wrote myself a wrapper class for System::Threading::Thread because I know I will be using them alot. I gave the class various delegate events so it can interact with the UI thread. I've been using it mainly just to set the status of the status bar. I also had a progress bar that had been unused, so I wanted to add it. I gave it a delegate, but when I run it, it crashes with the infamous:

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll

Additional information: Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.

I'm confused now, because as far as I know I'm using the delegate the same way I do it with other controls. Is this one special? I've searched the internet far and wide and all I get is C# BackgroundWorker questions, which don't really apply to this. Here is the code for my delegate:

The delegate:

delegate void               OnThreadProgressUpdateDel(int progress, String^ status);

The variable that holds the events:

OnThreadProgressUpdateDel^  m_updateProgressEvent;

The way the event is bound:

thread->OnThreadProgressUpdate += gcnew ObjectLoadThread::OnThreadProgressUpdateDel(this, &CObjectLoader::ProgressUpdate);

The event called:

void CObjectLoader::ProgressUpdate(int progress, String^ status)
{
    gGlobal->ProgramProgress->Maximum = 100;
    gGlobal->ProgramProgress->Value = progress; //Crash here...
    gGlobal->SetProgramStatus(status);
}

Called here:

m_updateProgressEvent->Invoke(1, "Loading objects...");

What's so special about this silly ToolStripProgressBar that makes it not want to update :(

Using C++ CLR, Windows Forms Application, in Microsoft Visual C++ 2008 Express Edition.

Upvotes: 2

Views: 2825

Answers (3)

abobjects.com
abobjects.com

Reputation: 141

// use below code Ahmad abbulkmailer.com

SetControlPropertyValue1(ProgressBar2, "value", 67);

  delegate void SetControlValueCallback1(ToolStripProgressBar oControl, string propName, object propValue);
        private void SetControlPropertyValue1(ToolStripProgressBar oControl, string propName, object propValue) {
            if (oControl.GetCurrentParent().InvokeRequired) {
                SetControlValueCallback1 d = new SetControlValueCallback1(SetControlPropertyValue1);
                oControl.GetCurrentParent().Invoke(d, new object[] { oControl, propName, propValue });
            }
            else {

                Type t = oControl.GetType();
                PropertyInfo[] props = t.GetProperties();

                foreach (PropertyInfo p in props) {
                    if (p.Name.ToUpper() == propName.ToUpper()) {
                        p.SetValue(oControl, propValue, null);
                    }
                }
            }
            

        }

Upvotes: 0

Ryan
Ryan

Reputation: 31

"ToolStripProgressBar doesn't have an Invoke method."

You're correct; however toolStripProgressBar.ProgressBar.Invoke and InvokeRequired do exist and function as expected.

Upvotes: 3

John Arlen
John Arlen

Reputation: 6689

Windows Controls want to be modified from the same thread they were created on. Depending on the control & operation, the MDA or Exception won't fire, but it's by far best to follow the standard:

if(InvokeRequired) control.Invoke();

pattern whenever dealing with threads and controls.

http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx

Upvotes: 1

Related Questions