diff options
author | Rob Wilkens <RobWilkens@gmail.com> | 2012-06-20 18:34:50 +0400 |
---|---|---|
committer | Rob Wilkens <RobWilkens@gmail.com> | 2012-06-20 18:34:50 +0400 |
commit | 38bdbad5071487a11f4330077c383375dce39840 (patch) | |
tree | f63ccdef20e18756ac51c94b808b78946262c870 /mcs/class/Managed.Windows.Forms/Test | |
parent | 8f07a57a4b05dc0cbd0ce93dec4a66002ab4ff42 (diff) |
Fix:Idle event handler was called on every thread rather than thread assigned on
Summary of changes in order git diff --staged is giving them to me:
(1) Each Xplat driver :
-local "Idle" variable remove, replaced with a Driver-level Idle_Threads
which is assigned by what is now the Idle Property.
-When Idle Called from with thread it used to do:
if (Idle != null)
Idle (this, e)
now we have to do some additional checks and change the call similar to as
follows to get the per-thread idle event handler:
(pseudo-pseudo-code)
id=ManagedThreadId;
if (Idle_Threads is not null and it contains a key for the id and the key
indexes into a non-null event handler) then
Idle_Threads [id] (this, e);
(2) Xplat Driver
Here's where the property is added and assigns the Idle event handler to
Idle_Threads. A Lock was needed the first time we create the Idle_Threads
dictionary. The Idle_Threads dictionary indexes by managed thread id and
maps onto an event handler for each one.
(3) Win32 Specific change
In my testing, I noticed that Win32 did not call Idle as part of its normal
Run loop processing. So, when it would call GetMessage and it was Blocking
we now check Idle if we were going to block. We don't actually call idle
if we first peekMessage and find a message, in those cases we just treat
it as if GetMessage Got the message. If we are blocking and peek returns
no messages, we call idle. If we have already called idle once on this
pass through the GetMessage Loop we set CheckIdle to false and go
back to the to to PRocessNextMEssage but this time we block rather than
peek and call idle.
This code was tested on Win32, MacOS/Carbon and Linux/X11. There have been
some minor formatting changes (Code style) since the testing, which should
not affect test results.
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/Test')
-rw-r--r-- | mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/FormEventTest.cs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/FormEventTest.cs b/mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/FormEventTest.cs index c2f3c375158..9a7e9bcfb40 100644 --- a/mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/FormEventTest.cs +++ b/mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/FormEventTest.cs @@ -624,6 +624,80 @@ namespace MonoTests.System.Windows.Forms _form.MinimumSize = new Size(100, 100); Assert.AreEqual (true, eventhandled, "#A10"); } + + /** + ** This next test is in response to a bug report + ** which pointed out that the idle events were being + ** sent to every thread rather than just the thread + ** they were assigned on. + ** + ** Report: https://bugzilla.novell.com/show_bug.cgi?id=321541 + **/ + private static Form form1_OneIdlePerThread = null; + private static Form form2_OneIdlePerThread = null; + private static int count1_OIPT = 0; + private static int count2_OIPT = 0; + private static ThreadStart OIPT_ThreadStart2; + private static Thread OIPT_Thread2; + private static int oipt_t1 = 0; + private static int oipt_t2 = 0; + [Test] + public void OneIdlePerThread () { + Thread t = Thread.CurrentThread; + oipt_t1 = t.ManagedThreadId; + count1_OIPT = 0; + count2_OIPT = 0; + form1_OneIdlePerThread = new Form (); + form2_OneIdlePerThread = new Form (); + form1_OneIdlePerThread.Show (); + + OIPT_ThreadStart2 = new ThreadStart (TIPT_Two); + OIPT_Thread2=new Thread (OIPT_ThreadStart2); + OIPT_Thread2.IsBackground = true; + OIPT_Thread2.SetApartmentState (ApartmentState.STA); + OIPT_Thread2.Start (); + Application.Idle += new EventHandler (TestIdlePerThread); + Application.Run (form1_OneIdlePerThread); + if (!OIPT_Thread2.Join (1000)){ + OIPT_Thread2.Abort(); + } + + Assert.AreEqual (true, count1_OIPT == 1, + "#Idle: idle #1 hit too many times"); + Assert.AreEqual (true, count2_OIPT == 1, + "#Idle: idle #2 hit too many times"); + } + public static void TIPT_Two (){ + Thread t = Thread.CurrentThread; + oipt_t2 = t.ManagedThreadId; + Application.Idle += + new EventHandler (TestIdlePerThread2); + Application.Run (form2_OneIdlePerThread); + } + public static void TestIdlePerThread (object o, EventArgs e) { + Thread t = Thread.CurrentThread; + count1_OIPT++; + Application.Idle -= + new EventHandler (TestIdlePerThread); + /* Give thread2 time to finish before we close */ + Thread.Sleep(100); + if (form1_OneIdlePerThread != null) + form1_OneIdlePerThread.Close (); + Assert.AreEqual (true, oipt_t1 == t.ManagedThreadId, + "#Idle:Wrong Thread-t1"); + } + public static void TestIdlePerThread2 (object o, EventArgs e) { + Thread t = Thread.CurrentThread; + count2_OIPT++; + Application.Idle -= + new EventHandler(TestIdlePerThread2); + if (form2_OneIdlePerThread != null) + form2_OneIdlePerThread.Invoke + (new MethodInvoker (form2_OneIdlePerThread.Close)); + Assert.AreEqual (true, oipt_t2 == t.ManagedThreadId, + "#Idle:Wrong Thread-t2"); + } + } [TestFixture] |