Reputation: 438
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
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
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
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