现在,我知道当大多数人看到这种问题时,他们会想“噢使用代表”。好吧,我使用委托。到目前为止,这是唯一拒绝与他们合作的控件。我也没有使用BackgroundWorker。
我自己写了一个System :: Threading :: Thread的包装类,因为我知道我将使用它们很多。我为类提供了各种委托事件,因此它可以与UI线程进行交互。我一直在使用它主要是为了设置状态栏的状态。我还有一个未使用的进度条,所以我想添加它。我给了它一个代表,但当我运行它时,它与臭名昭着的崩溃:
System.Windows.Forms.dll中出现未处理的“System.InvalidOperationException”类型异常
附加信息:跨线程操作无效:控制'' 从创建它的线程以外的线程访问。
我现在很困惑,因为据我所知,我正在使用委托,就像我使用其他控件一样。这个特别吗?我已经远程搜索了互联网,我得到的只是C#BackgroundWorker问题,这些问题并不适用于此。这是我的代表的代码:
代表:
delegate void OnThreadProgressUpdateDel(int progress, String^ status);
保存事件的变量:
OnThreadProgressUpdateDel^ m_updateProgressEvent;
事件的约束方式:
thread->OnThreadProgressUpdate += gcnew ObjectLoadThread::OnThreadProgressUpdateDel(this, &CObjectLoader::ProgressUpdate);
该事件名为:
void CObjectLoader::ProgressUpdate(int progress, String^ status)
{
gGlobal->ProgramProgress->Maximum = 100;
gGlobal->ProgramProgress->Value = progress; //Crash here...
gGlobal->SetProgramStatus(status);
}
在这里打电话:
m_updateProgressEvent->Invoke(1, "Loading objects...");
这个愚蠢的ToolStripProgressBar让它不想更新有什么特别之处:(
在Microsoft Visual C ++ 2008 Express Edition中使用C ++ CLR,Windows窗体应用程序。
答案 0 :(得分:2)
“ToolStripProgressBar没有Invoke方法。”
你是对的;但是toolStripProgressBar.ProgressBar.Invoke和InvokeRequired确实存在并按预期运行。
答案 1 :(得分:1)
Windows控件希望从创建它们的同一个线程进行修改。取决于控制和&操作,MDA或Exception不会触发,但它最好遵循标准:
if(InvokeRequired) control.Invoke();
模式。
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
答案 2 :(得分:0)
//使用以下代码Ahmad abbulkmailer.com
SetControlPropertyValue1(ProgressBar2,“value”,67);
委托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}); } 别的{
Type t = oControl.GetType();
PropertyInfo[] props = t.GetProperties();
foreach (PropertyInfo p in props) {
if (p.Name.ToUpper() == propName.ToUpper()) {
p.SetValue(oControl, propValue, null);
}
}
}
}