help explain this winform behaviour

D

dadizhu

Hi, everyone. I ran into an UI freeze issue with threading and
simplied the problem down to the following sample code. The logic is
as follows:

1. The main UI thread creates a non-UI STA thread(m_MainThread).
2. Then the non-UI thread runs and creates derived winform and holds
a reference to the winform. NOTE: I don't call Application.Run()
because I don't need a message pump on this "hidden form" in my
application. I rely on the form's STA thread owner to pump and
dispatch non-COM messages to the form window on a WaitOne() call.
This works fine. I can send and receive messages to external win32
process using the hidden form.

The code below works fine in .NET 1.1, but causes UI freeze issue
in .NET 2.0 outside of the debugger. To produce the freeze behaviour,
I do the following:

1. Run the winform test app below outside of debugger.
2. Click on the Start button to create the non-UI thread(which
creates the hidden form)
3. right click on Desktop -> Properties -> Settings -> change your
screen resolution to something less and click OK
4. When asked if you want to keep the setting, click NO to go back.

At this point, you will notice that the main form is now
frozen(verified with spy++ that it doesn't get any messages). It
looks like it's deactivated somehow. You can't move the window and
the form won't paint properly if you overlap it with another window.

The same code below doesn't have the problem in .NET 1.1. Also, the
problem doesn't occur in .NET 2.0 if you run it under the debugger.

If I don't create the hidden winform, there is no problem.

Can someone explain what's happening? Thanks.


================= Code Starts Here =================

public partial class Form1 : Form
{
AutoResetEvent m_MainThreadStopEvent = new
AutoResetEvent(false);
Thread m_MainThread = null;
HiddenForm m_WorkerHiddenForm = null;

public Form1()
{
InitializeComponent();
}

private void Start()
{
m_MainThread = new Thread(new
ThreadStart(MainThreadStart));
m_MainThread.Name = "My Main Thread";
m_MainThread.SetApartmentState(ApartmentState.STA);
m_MainThread.Start();
}

private void Stop()
{
m_MainThreadStopEvent.Set();
}

private void MainThreadStart()
{
System.Diagnostics.Debug.WriteLine("Created Main
Thread ... " + DateTime.Now.ToLongTimeString());
m_WorkerHiddenForm = new HiddenForm();

while (!m_MainThreadStopEvent.WaitOne(5000, true))
{
System.Diagnostics.Debug.WriteLine("::MainThread ... "
+ DateTime.Now.ToLongTimeString());
}
m_WorkerHiddenForm.Close();

System.Diagnostics.Debug.WriteLine("Stopped Main
Thread ... " + DateTime.Now.ToLongTimeString());
}

private void btnStart_Click(object sender, EventArgs e)
{
Start();
}

private void btnStop_Click(object sender, EventArgs e)
{
Stop();
}

private void Form1_FormClosing(object sender,
FormClosingEventArgs e)
{
Stop();
}
}


public class HiddenForm : Form
{
int m_WindowHandle;
public HiddenForm()
{
m_WindowHandle = this.Handle.ToInt32();
}

protected override void WndProc(ref Message msg)
{
base.WndProc(ref msg);
}
}
 
C

ClayB

Just something to try. In your hidden form code, if you an
InvokeRequired check to the WndProc override, does it verify you are
on the proper thread?

protected override void WndProc(ref Message msg)
{
if(this.InvokeRequired())
throw new Exception("Wrong thread");
base.WndProc(ref msg);
}

===================
Clay Burch
Syncfusion, Inc.
 

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