c# – Diagnosing GUI RichTextBox

Question:

The application hangs tightly when logging in via RDesktop (standard Windows remote desktop) to a remote Windows Server 2008 (logged out, logged in – wow, hung). The problem boils down to this simple code:

  ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
  {
     var richTextBox = new RichTextBox();

     while (true)
     {
       richTextBox.AppendText("a");//источник зла
     }

   }), SynchronizationContext.Current);

richTextBox is initially in a child thread, so InvokeRequired=false, there should be no conflict with the GUI. The question is, what could be the problem, where to start diagnosing?

update

another look at the problem:

  ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
  {
       var richTextBox = new RichTextBox();

       //Thread.Sleep(10000);//вышел-зашел в RDesktop -все нормально
       richTextBox.AppendText("a");//источник зла
       Thread.Sleep(10000);//вышел-зашел в RDesktop- приложение виснет

   }), SynchronizationContext.Current);

Update 2

The same error occurs with the splash screen .

More on the topic:

Initial task

It is required in a separate (not main) thread to form a large RTF. RTF is needed because font formatting is required (different font sizes, etc.) Then save to richTextBox.Save file (.rtf file)

Answer:

I have this (or similar) problem reproduced on Win 2008 R2, but it does not freeze completely, but for 10 seconds. WinDbg shows the following trace:

0043e8f8 779801a9 [HelperMethodFrame_1OBJ: 0043e8f8] System.Threading.WaitHandle.WaitOneNative(System.Runtime.InteropServices.SafeHandle, UInt32, Boolean, Boolean)
0043e9c4 70726dd2 System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle, Int64, Boolean, Boolean)
0043e9e0 70726d9c System.Threading.WaitHandle.WaitOne(Int32, Boolean)
0043e9f4 6df04246 System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle)
0043ea30 6e2657bf System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control, System.Delegate, System.Object[], Boolean)
0043ea34 6defce3b [InlinedCallFrame: 0043ea34] 
0043eabc 6defce3b System.Windows.Forms.Control.Invoke(System.Delegate, System.Object[])
0043eaf0 6e13bf99 System.Windows.Forms.WindowsFormsSynchronizationContext.Send(System.Threading.SendOrPostCallback, System.Object)
0043eb08 700c5c23 Microsoft.Win32.SystemEvents+SystemEventInvokeInfo.Invoke(Boolean, System.Object[])
0043eb3c 700c5533 Microsoft.Win32.SystemEvents.RaiseEvent(Boolean, System.Object, System.Object[])
0043eb90 700c5123 Microsoft.Win32.SystemEvents.OnUserPreferenceChanged(Int32, IntPtr, IntPtr)
0043ebb0 7028bb60 Microsoft.Win32.SystemEvents.WindowProc(IntPtr, Int32, IntPtr, IntPtr)
0043ebb4 000ca24a [InlinedCallFrame: 0043ebb4] 
0043ed64 000ca24a [InlinedCallFrame: 0043ed64] 
0043ed60 6d9c976c DomainBoundILStubClass.IL_STUB_PInvoke(MSG ByRef)
0043ed64 6d97f341 [InlinedCallFrame: 0043ed64] System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)
0043ed98 6d97f341 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, Int32, Int32)
0043ed9c 6d97efc1 [InlinedCallFrame: 0043ed9c] 
0043ee24 6d97efc1 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
0043ee74 6d97ee32 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
0043eea0 6d958a41 System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
0043eeb4 001e007a WindowsFormsApplication2.Program.Main()
0043f03c 71463de2 [GCFrame: 0043f03c] 

After that, a bunch of exceptions drops out in debugging

System.ComponentModel.InvalidAsynchronousStateException

An error occurred invoking the method. The destination thread no longer exists.

Apparently, when logging in via the remote, the system tries to send OnUserPreferenceChanged to all windows. RTB is a window, and the message stupidly does not reach it – because the thread in which RTB is created is busy adding letters or sleeping at that time.

It stops hanging for me if I take a thread not from the pool, but create a new one:

new Thread(() =>
{
    var richTextBox = new RichTextBox();

    //Thread.Sleep(10000);//вышел-зашел в RDesktop -все нормально
    richTextBox.AppendText("a");//источник зла
    Thread.Sleep(100);//вышел-зашел в RDesktop- приложение виснет

}).Start();

Exceptions are still visible in debug, but they are thrown immediately and there is no hang.

UP:

UserPreferenceChanged contains a description of this particular problem:

Applications should never leave Control objects on threads without an active message pump. If Controls cannot be created on the main UI thread, they should be created on a dedicated secondary UI thread and Disposed as soon as they are no longer needed.

So if you want a reliable solution – run the second pump:

new Thread(() =>
{
    Application.Run(new Скрытая_Форма_С_RTB_на_ней());            
}).Start();

and close this form as soon as it is no longer needed.

Scroll to Top