[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnetlib/System.Windows.Forms Application.cs, 1.5, 1.6,
Rhys Weatherley <address@hidden> <=
- Prev by Date:
[Dotgnu-pnet-commits] CVS: pnet/include il_linker.h, 1.16, 1.17 il_writer.h, 1.7, 1.8
- Next by Date:
[Dotgnu-pnet-commits] CVS: pnetlib ChangeLog,1.1133,1.1134
- Previous by thread:
[Dotgnu-pnet-commits] CVS: pnet/include il_linker.h, 1.16, 1.17 il_writer.h, 1.7, 1.8
- Next by thread:
[Dotgnu-pnet-commits] CVS: pnetlib ChangeLog,1.1133,1.1134
- Index(es):