从父线程到子线程的通信

时间:2012-11-12 19:39:54

标签: c# multithreading

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

'不能使用已与其基础RCW分离的COM对象。'

我的问题是我无法弄清楚如何引用相关的webbrowser控件。我很感激任何人都可以给我的帮助。

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

代码示例:

当用户单击主线程中的“开始”按钮时,将执行以下代码

private void StartSubmit(object idx) {

/ *

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

* /

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

int index =(int)idx;

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

submitters[index] = new myBrowser();

// threads integer id

submitters[index]._ThreadNum = index;

//命名约定使用'browser'+线程索引

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

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

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

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

submitters[index].ScriptErrorsSuppressed = true;

//执行eventHandler

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'控件完全加载,我将表单数据插入到通过数据加载的网页中找到的webforms中,输入到datagridview中的行。一旦用户将相关细节输入到行中的不同区域,则可以 单击DataGridViewButtonCell,它收集输入的数据,然后必须发送回子线程上找到的相应“myBrowser”对象。

谢谢

2 个答案:

答案 0 :(得分:1)

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

顺便提一下,RCW代表Runtime Callable Wrapper。

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

答案 1 :(得分:0)

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

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