Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Wilkens <RobWilkens@gmail.com>2012-06-20 18:34:50 +0400
committerRob Wilkens <RobWilkens@gmail.com>2012-06-20 18:34:50 +0400
commit38bdbad5071487a11f4330077c383375dce39840 (patch)
treef63ccdef20e18756ac51c94b808b78946262c870 /mcs/class/Managed.Windows.Forms/Test
parent8f07a57a4b05dc0cbd0ce93dec4a66002ab4ff42 (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.cs74
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]