Reputation: 21
I have a List of threads normally 3 threads each of the threads reference a webbrowser control that communicates with the parent control to populate a datagridview. What I need to do is when the user clicks the button in a datagridviewButtonCell corresponding data will be sent back to the webbrowser control within the child thread that originally communicated with the main thread. but when I try to do this I receive the following error message
'COM object that has been separated from its underlying RCW cannot be used.'
my problem is that I can not figure out how to reference the relevant webbrowser control. I would appreciate any help that anyone can give me.
The language used is c# winforms .Net 4.0 targeted
Code sample:
The following code is executed when user click on the Start button in the main thread
private void StartSubmit(object idx) {
/*
method used by the new thread to initialise a 'myBrowser' inherited from the webbrowser control each submitters object is an a custom Control called 'myBrowser' which holds detail about the function of the object eg:
*/
//index: is an integer value which represents the threads id
int index = (int)idx;
//submitters[index] is an instance of the 'myBrowser' control
submitters[index] = new myBrowser();
//threads integer id
submitters[index]._ThreadNum = index;
// naming convention used 'browser' +the thread index
submitters[index].Name = "browser" + index;
//set list in 'myBrowser' class to hold a copy of the list found in the main thread
submitters[index]._dirs = dirLists[index];
// suppress and javascript errors the may occur in the 'myBrowser' control
submitters[index].ScriptErrorsSuppressed = true;
//execute eventHandler
submitters[index].DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(DocumentCompleted);
//advance to the next un-opened address in datagridview the navigate the that address
//in the 'myBrowser' control.
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);
}
}
Once the 'myBrowser' control is fully loaded I am inserting form data into webforms found in webpages loaded via data enter into rows found in the datagridview. Once a user has entered the relevant details into the different areas in the row the can then clicking a DataGridViewButtonCell that has tha collects the data entered and then has to be send back to the corresponding 'myBrowser' object that is found on a child thread.
Thank you
Upvotes: 2
Views: 1253
Reputation: 2970
COM objects are reference-counted (see IUnknown). obj->AddRef
increments the reference count and obj->Release()
decrements it. When the reference counter reaches zero, the object deallocates its memory and goes away, and that is what has happened when this error occurs.
Dispose
doesn't necessarily call Release
- the way to do that for a COM object is to call Marshal.ReleaseComObject. Finalizing an object would release it, however. Make sure your web browser control stays in scope, and make sure it isn't actually accessed on any threads other than the main UI thread.
Upvotes: 0
Reputation: 150108
That error indicates that the managed object wrapping the COM object (probably the WebBrowser control, but I can't be sure without more information) has been disposed. That means that the managed object still exists (it has not been garbage collected), but IDisposable.Dispose() has been called on it (which releases the WebBrowser control, which is a COM object).
RCW, by the way, stands for Runtime Callable Wrapper.
Ensure that the COM object you are trying to reference via it's managed wrapper has not had IDisposable.Dispose called on it (directly, or e.g. by leaving the scope of a using block).
Upvotes: 1