【问题标题】:Communication from Parent thread to child thread父线程到子线程的通信
【发布时间】:2012-11-01 06:27:03
【问题描述】:

我有一个线程列表,通常有 3 个线程,每个线程引用一个与父控件通信以填充数据网格视图的 webbrowser 控件。我需要做的是,当用户单击 datagridviewButtonCell 中的按钮时,相应的数据将被发送回最初与主线程通信的子线程内的 webbrowser 控件。但是当我尝试这样做时,我收到以下错误消息

'不能使用已经与其底层 RCW 分离的 COM 对象。'

我的问题是我不知道如何引用相关的浏览器控件。任何人都可以给我任何帮助,我将不胜感激。

使用的语言是c# winforms .Net 4.0 目标

代码示例:

当用户点击主线程中的开始按钮时,会执行以下代码

private void StartSubmit(object idx) {

/*

新线程用于初始化从 webbrowser 控件继承的“myBrowser”的方法每个提交者对象都是一个名为“myBrowser”的自定义控件 其中包含有关对象功能的详细信息,例如:

*/

//index:是一个整数值,代表线程id

int 索引 = (int)idx;

//submitters[index] 是 'myBrowser' 控件的一个实例

submitters[index] = new myBrowser();

//线程整数id

submitters[index]._ThreadNum = index;

// 命名约定使用“浏览器”+线程索引

submitters[index].Name = "browser" + index;

//在“myBrowser”类中设置列表以保存在主线程中找到的列表的副本

submitters[index]._dirs = dirLists[index];

//抑制'myBrowser'控件中可能出现的javascript错误

submitters[index].ScriptErrorsSuppressed = true;

//执行事件处理程序

submitters[index].DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentCompleted);

//前进到datagridview中下一个未打开的地址导航该地址

//在“myBrowser”控件中。

SetNextDir(submitters[index]);

}

private void btnStart_Click(object sender, EventArgs e) {

  // used to fill list<string> for use in each thread.

  fillDirs();

  //connections is the list<Thread> holding the thread that have been opened
  //1 to 10 maximum

  for (int n = 0; n < (connections.Length); n++)

  {

     //initialise new thread to the StartSubmit method passing parameters

     connections[n] = new Thread(new ParameterizedThreadStart(StartSubmit));

     // naming convention used conn + the threadIndex ie: 'conn1' to 'conn10' 

     connections[n].Name = "conn" + n.ToString();

     // due to the webbrowser control needing to be ran in the single
     //apartment state

     connections[n].SetApartmentState(ApartmentState.STA);

     //start thread passing the threadIndex

     connections[n].Start(n);

  }

}

“myBrowser”控件完全加载后,我将表单数据插入到网页中的 web 表单中,这些网页通过数据加载到 datagridview 中的行中。一旦用户将相关详细信息输入到行中的不同区域,然后 单击具有 tha 的 DataGridViewButtonCell 收集输入的数据,然后必须将其发送回在子线程上找到的相应“myBrowser”对象。

谢谢

【问题讨论】:

  • WebBrowser 和线程是水和火。您必须调用 Thread.SetApartmentState() 来切换到 STA,泵送消息循环并在可以使用浏览器的情况下保持线程处于活动状态。

标签: c# multithreading


【解决方案1】:

该错误表明包装 COM 对象的托管对象(可能是 WebBrowser 控件,但如果没有更多信息我无法确定)已被释放。这意味着托管对象仍然存在(它还没有被垃圾回收),但是已经调用了 IDisposable.Dispose() (这会释放 WebBrowser 控件,它是一个 COM 对象)。

顺便说一下,R​​CW 代表 Runtime Callable Wrapper。

确保您尝试通过它的托管包装器引用的 COM 对象没有调用 IDisposable.Dispose(直接调用,或者例如通过离开 using 块的范围)。 p>

【讨论】:

    【解决方案2】:

    COM 对象是引用计数的(请参阅IUnknown)。 obj-&gt;AddRef 增加引用计数,obj-&gt;Release() 减少它。当引用计数器达到零时,对象释放其内存并消失,这就是发生此错误时发生的情况。

    Dispose 不一定调用Release - 对 COM 对象执行此操作的方法是调用 Marshal.ReleaseComObject。然而,完成一个对象会释放它。确保您的 Web 浏览器控件保持在范围内,并确保它实际上没有在主 UI 线程以外的任何线程上被访问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-30
      • 1970-01-01
      • 1970-01-01
      • 2018-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多