DisconnectedContext was detected - WebBrowser.Document.Write

Z

Zytan

Make a WebBrowser control, and make a bunch of timers / threads that
continually call WebBrowser.Document.Write. Eventually, this happens:

DisconnectedContext was detected
Message: Context 0x1a1530' is disconnected. Releasing the interfaces
from the current context (context 0x1a13c0).This may cause corruption
or data loss. To avoid this problem, please ensure that all contexts/
apartments stay alive until the applicationis completely done with the
RuntimeCallableWrappers that represent COM components that liveinside
them.

I believe that eventually the WebBrowser takes so long to refresh that
it doesn't complete its job before the next Write, and this occurs.
This explains why it occurs quicker if the Writing speed is increased,
and why it always enivitably happens, even if the writing speed is
slowed. Since, as the page grows in size, the refresh time increases.

Any fixes? It just happens. I can't catch it as an exception.

Zytan
 
Z

Zytan

Furthermore, if I tell the debugger to continue after the
"DisconnectedContext was detected " error, this occurs:

ContextSwitchDeadlock was detected
Message: The CLR has been unable to transition from COM context
0x1a0ba0 to COM context 0x1a0d10 for 60 seconds. The thread that owns
the destination context/apartment is most likely either doing a non
pumping wait or processing a very long running operation without
pumping Windows messages. This situation generally has a negative
performance impact and may even lead to the application becoming non
responsive or memory usage accumulating continually over time. To
avoid this problem, all single threaded apartment (STA) threads should
use pumping wait primitives (such as CoWaitForMultipleHandles) and
routinely pump messages during long running operations.

Zytan
 
N

Nicholas Paldino [.NET/C# MVP]

What kind of timers are you using, and how are you making the calls? It
looks like you are trying to do a cross apartment call, when in fact, if
your timers are firing on a non-UI thread, you should be making your calls
to Document.Write through a delegate passed to the Invoke method on the
WebBrowser control.
 
Z

Zytan

What kind of timers are you using,

The standard Timer control. I don't need any timers to cause this.
In fact, my latest test program has no timers.
and how are you making the calls?

I am calling WebBrowser.InvokeRequired to see if the thread is in the
right thread. If true: it calls WebBrowser.BeginInvoke (asynchronous)
to call the same function from the GUI thread. If false: it runs
WebBrowser.Write.
It
looks like you are trying to do a cross apartment call, when in fact, if
your timers are firing on a non-UI thread, you should be making your calls
to Document.Write through a delegate passed to the Invoke method on the
WebBrowser control.

Forget about the Timer controls, since they just confuse the issue at
hand, I am sorry I brought them up. And I believe I am already doing
the rest, as you suggest, properly. I can post a small source
example, if you wish.

Thanks, Nicholas

Zytan
 
Z

Zytan

and how are you making the calls?
I am calling WebBrowser.InvokeRequired to see if the thread is in the
right thread. If true: it calls WebBrowser.BeginInvoke (asynchronous)
to call the same function from the GUI thread. If false: it runs
WebBrowser.Write.

Note that if I make the program repeatedly call all the above from the
GUI thread (say, in response to a button click), where no other
threads exist, then it can write and write and write, and nothing bad
happens.

The error occurs only when non-GUI threads are doing the writing. In
fact, ONLY ONE non-GUI thread needs to be writing to it to cause the
error (without the GUI thread doing anything itself).

Zytan
 
Z

Zytan

Source code: Three buttons: START, STOP (starts and stops worker
threads), and GUITHREAD (does work in the main gui thread). The code
isn't 'perfect' in that if you keep clicking START over and over, and
it makes more and more threads, using the same variable reference over
and over.

namespace MultithreadGUI
{
public partial class MainForm : Form
{
private Thread myThread;
private volatile bool m_bThreadRunning = false;

public MainForm()
{
InitializeComponent();
}

private void MainForm_FormClosed(object sender,
FormClosedEventArgs e)
{
m_bThreadRunning = false;
}

delegate void MyWriteLine_Delegate(string s);
private void MyWriteLine(string s)
{
if (webLog.InvokeRequired)
{
MyWriteLine_Delegate funcPtr = MyWriteLine;
object[] argArray = { s };
webLog.BeginInvoke(funcPtr, argArray);

}
else
{
if (webLog.Document == null)
webLog.Navigate("about:blank");
webLog.Document.Write(s + "<br>" +
Environment.NewLine);
webLog.Document.Window.ScrollTo(0, int.MaxValue);
}
}

private int m_countThread1 = 0;
private void myThreadFunc1()
{
while (m_bThreadRunning)
{
// Thread.Sleep(400);
m_countThread1++;
MyWriteLine("m_countThread1 = " + m_countThread1);
}
}

private void btnStart_Click(object sender, EventArgs e)
{
m_bThreadRunning = true;
myThread = new Thread(myThreadFunc1);
myThread.Start();
}

private void btnStop_Click(object sender, EventArgs e)
{
m_bThreadRunning = false;
}

private void btnGuiThread_Click(object sender, EventArgs e)
{
for (int i = 0; i < 1000000000; i++)
MyWriteLine(i + ": " + Guid.NewGuid().ToString());
}
}
}

Try these things:

1. click GUITHREAD, all is ok.
2. click START it breaks down (just one worker thread)
3. add Thread.Sleep() to slow it down, and keep pressing START over
and over (or hold ENTER down if it's in focus to keep pressing it),
and wait, it breaks down.

Zytan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top