2

现在,我知道当大多数人看到这种问题时,他们会想“哦,使用代表”。好吧,我正在使用代表。这是迄今为止唯一拒绝与他们合作的控件。我也没有使用 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 窗体应用程序。

4

3 回答 3

3

“ToolStripProgressBar 没有 Invoke 方法。”

你是对的;但是 toolStripProgressBar.ProgressBar.Invoke 和 InvokeRequired 确实存在并且按预期运行。

于 2012-05-18T20:56:44.200 回答
1

Windows 控件希望从创建它们的同一线程进行修改。根据控制和操作,MDA 或 Exception 不会触发,但到目前为止最好遵循标准:

if(InvokeRequired) control.Invoke();

处理线程和控件时的模式。

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

于 2012-04-24T21:02:31.560 回答
0

// 使用下面的代码 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);
                    }
                }
            }
            

        }
于 2014-04-16T15:32:47.847 回答