2012-11-12 33 views
2

我有一個線程列表,通常每個線程有3個線程引用一個webbrowser控件,它與父控件通信以填充datagridview。我需要做的是,當用戶點擊datagridviewButtonCell中的按鈕時,相應的數據將被髮回到最初與主線程通信的子線程內的webbrowser控件。但是當我嘗試執行此操作時,我收到以下錯誤消息從父線程到子線程的通信

'已與其基礎RCW分離的COM對象無法使用。'

我的問題是,我無法弄清楚如何引用相關的瀏覽器控件。我將不勝感激任何人都可以給我的幫助。

使用的語言是C#的WinForms .NET 4.0的目標

代碼示例:

執行下面的代碼時,在主線程

私人無效StartSubmit上的開始按鈕,用戶點擊(對象IDX) {

/*

方法中使用由新的線程來初始化從web瀏覽器控件中的每個提交者對象繼承了「myBrowser」是所謂的「myBrowser」 自定義控制,其保持關於該對象例如功能細節:

*/

// index:是表示線程ID的整數值。

//提議者[指數]是 '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].DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentCompleted); 

//前進到下一個未打開的地址在datagridview中導航該地址

//在'myBrowser'控件中。

SetNextDir(submitters[index]); 

}

私人無效btnStart_Click(對象發件人,EventArgs的) {

// 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,該DataGridViewButtonCell會收集輸入的數據,然後必須發回到在子線程上找到的相應'myBrowser'對象。

謝謝

+0

Web瀏覽器和線程是水和火。您必須調用Thread.SetApartmentState()才能切換到STA,只要瀏覽器可以使用,就會抽取一個消息循環並保持線程處於活動狀態。 –

+0

[WebBrowser控件在新線程中可能的重複](http://stackoverflow.com/questions/4269800/webbrowser-control-in-a-new-thread) –

回答

1

這錯誤表明管理對象包裝COM對象(可能WebBrowser控件,但我不能肯定沒有更多的信息),已被釋放。這意味着託管對象仍然存在(它沒有被垃圾回收),但是它已經調用了IDisposable.Dispose()(它釋放了WebBrowser控件,它是一個COM對象)。

順便說一下,R​​CW代表Runtime Callable Wrapper。

確保您嘗試通過它的託管包裝引用的COM對象沒有對其調用IDisposable.Dispose(直接,或者例如通過使用塊保留範圍)。

0

COM對象是引用計數的(請參閱IUnknown)。 obj->AddRef遞增引用計數,obj->Release()遞減計數。當引用計數器達到零時,對象將釋放其內存並消失,這就是發生此錯誤時發生的情況。

Dispose不一定會調用Release - 對COM對象執行此操作的方法是調用Marshal.ReleaseComObject。然而,完成一個對象會釋放它。確保您的Web瀏覽器控件保持在範圍內,並確保它不是在主UI線程以外的任何線程上實際訪問的。