dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dotgnu-pnet-commits] CVS: pnetlib/System.Windows.Forms Application.cs,


From: Rhys Weatherley <address@hidden>
Subject: [Dotgnu-pnet-commits] CVS: pnetlib/System.Windows.Forms Application.cs, 1.5, 1.6
Date: Wed, 09 Jul 2003 00:41:12 -0400

Update of /cvsroot/dotgnu-pnet/pnetlib/System.Windows.Forms
In directory subversions:/tmp/cvs-serv18518/System.Windows.Forms

Modified Files:
        Application.cs 
Log Message:


Put some infrastructure in place to support multi-threaded Forms
applications - sending requests to another thread's message loop
for execution.


Index: Application.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Windows.Forms/Application.cs,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -r1.5 -r1.6
*** Application.cs      22 Jun 2003 03:19:45 -0000      1.5
--- Application.cs      9 Jul 2003 04:41:09 -0000       1.6
***************
*** 33,36 ****
--- 33,38 ----
        // Internal state.
        private static ApplicationContext context;
+       private static Request requests;
+       private static Request lastRequest;
  
        // Cannot instantiate this class.
***************
*** 283,297 ****
        public static void DoEvents()
                        {
!                               // Make sure that this thread has a message 
loop running.
                                lock(typeof(Application))
                                {
!                                       if(mainThread != Thread.CurrentThread)
!                                       {
!                                               return;
!                                       }
                                }
  
                                // Process pending events.
!                               ToolkitManager.Toolkit.ProcessEvents(false);
                        }
  
--- 285,309 ----
        public static void DoEvents()
                        {
!                               bool isMainThread;
!                               Thread thread = Thread.CurrentThread;
!                               Request request;
! 
!                               // Determine if we are the main thread.
                                lock(typeof(Application))
                                {
!                                       isMainThread = (mainThread == thread);
                                }
  
                                // Process pending events.
!                               if(isMainThread)
!                               {
!                                       
ToolkitManager.Toolkit.ProcessEvents(false);
!                               }
! 
!                               // Process requests that were sent via 
"SendRequest".
!                               while((request = NextRequest(thread, false)) != 
null)
!                               {
!                                       request.Execute();
!                               }
                        }
  
***************
*** 325,328 ****
--- 337,343 ----
                                Form mainForm = context.MainForm;
                                EventHandler handler;
+                               Request request;
+                               Thread thread = Thread.CurrentThread;
+                               bool isMainThread;
  
                                // Connect the context's ThreadExit event to 
our "ExitThread".
***************
*** 342,383 ****
                                        if(mainThread != null)
                                        {
!                                               throw new 
InvalidOperationException
!                                                       
(S._("SWF_MessageLoopAlreadRunning"));
                                        }
-                                       mainThread = Thread.CurrentThread;
                                }
  
                                // Run the main message processing loop.
!                               IToolkit toolkit = ToolkitManager.Toolkit;
!                               try
                                {
!                                       for(;;)
                                        {
!                                               // Process events in the queue.
!                                               
if(!toolkit.ProcessEvents(false))
                                                {
!                                               #if !CONFIG_COMPACT_FORMS
!                                                       // There were no 
events, so raise "Idle".
!                                                       if(Idle != null)
                                                        {
!                                                               Idle(null, 
EventArgs.Empty);
                                                        }
!                                               #endif
! 
!                                                       // Block until the next 
event, or quit, arrives.
!                                                       
if(!toolkit.ProcessEvents(true))
                                                        {
!                                                               break;
                                                        }
                                                }
                                        }
                                }
!                               finally
                                {
!                                       // Reset the "mainThread" variable 
because there
!                                       // is no message loop any more.
!                                       lock(typeof(Application))
                                        {
!                                               mainThread = null;
                                        }
                                }
--- 357,420 ----
                                        if(mainThread != null)
                                        {
!                                               isMainThread = false;
!                                       }
!                                       else
!                                       {
!                                               mainThread = thread;
!                                               isMainThread = true;
                                        }
                                }
  
                                // Run the main message processing loop.
!                               if(isMainThread)
                                {
!                                       IToolkit toolkit = 
ToolkitManager.Toolkit;
!                                       try
                                        {
!                                               for(;;)
                                                {
!                                                       // Process events in 
the queue.
!                                                       
if(!toolkit.ProcessEvents(false))
                                                        {
!                                                       #if 
!CONFIG_COMPACT_FORMS
!                                                               // There were 
no events, so raise "Idle".
!                                                               if(Idle != null)
!                                                               {
!                                                                       
Idle(null, EventArgs.Empty);
!                                                               }
!                                                       #endif
!       
!                                                               // Block until 
an event, or quit, arrives.
!                                                               
if(!toolkit.ProcessEvents(true))
!                                                               {
!                                                                       break;
!                                                               }
                                                        }
!       
!                                                       // Process requests 
sent via "SendRequest".
!                                                       while((request = 
NextRequest(thread, false))
!                                                                               
!= null)
                                                        {
!                                                               
request.Execute();
                                                        }
                                                }
                                        }
+                                       finally
+                                       {
+                                               // Reset the "mainThread" 
variable because there
+                                               // is no message loop any more.
+                                               lock(typeof(Application))
+                                               {
+                                                       mainThread = null;
+                                               }
+                                       }
                                }
!                               else
                                {
!                                       // This is not the main thread, so only 
process
!                                       // requests that were sent via 
"SendRequest".
!                                       while((request = NextRequest(thread, 
true)) != null)
                                        {
!                                               request.Execute();
                                        }
                                }
***************
*** 430,433 ****
--- 467,561 ----
  
  #endif // !CONFIG_COMPACT_FORMS
+ 
+       // Information about a request to be executed in a specific thread.
+       // This is used to help implement the "Control.Invoke" method.
+       internal abstract class Request
+       {
+               public Request next;
+               public Thread thread;
+ 
+               // Execute the request.
+               public abstract void Execute();
+ 
+       }; // class Request
+ 
+       // Send a request to a particular thread's message queue.
+       internal static void SendRequest(Request request, Thread thread)
+                       {
+                               Object obj = typeof(Application);
+                               request.thread = thread;
+                               lock(obj)
+                               {
+                                       // Add the request to the queue.
+                                       request.next = null;
+                                       if(requests != null)
+                                       {
+                                               lastRequest.next = request;
+                                       }
+                                       else
+                                       {
+                                               requests = request;
+                                       }
+                                       lastRequest = request;
+ 
+                                       // Wake up all threads that are 
blocking in "NextRequest".
+                                       Monitor.PulseAll(obj);
+ 
+                                       // Wake up the thread that will receive 
the request,
+                                       // as it may be blocking inside 
"ProcessEvents".
+                                       ToolkitManager.Toolkit.Wakeup(thread);
+                               }
+                       }
+ 
+       // Get the next pending request for a particular thread.
+       private static Request NextRequest(Thread thread, bool block)
+                       {
+                               Object obj = typeof(Application);
+                               Request request, prev;
+                               lock(obj)
+                               {
+                                       for(;;)
+                                       {
+                                               // See if there is a request on 
the queue for us.
+                                               prev = null;
+                                               request = requests;
+                                               while(request != null)
+                                               {
+                                                       if(request.thread == 
thread)
+                                                       {
+                                                               if(prev != null)
+                                                               {
+                                                                       
prev.next = request.next;
+                                                               }
+                                                               else
+                                                               {
+                                                                       
requests = request.next;
+                                                               }
+                                                               if(request.next 
== null)
+                                                               {
+                                                                       
lastRequest = prev;
+                                                               }
+                                                               else
+                                                               {
+                                                                       
request.next = null;
+                                                               }
+                                                               break;
+                                                       }
+                                                       prev = request;
+                                                       request = request.next;
+                                               }
+ 
+                                               // Bail out if we got something 
or we aren't blocking.
+                                               if(request != null || !block)
+                                               {
+                                                       break;
+                                               }
+ 
+                                               // Wait to be signalled by 
"SendRequest".
+                                               Monitor.Wait(obj);
+                                       }
+                               }
+                               return request;
+                       }
  
  }; // class Application





reply via email to

[Prev in Thread] Current Thread [Next in Thread]