소스 검색

* Fix for bug ID #27628

git-svn-id: trunk@30153 -
michael 10 년 전
부모
커밋
0b52513c18
1개의 변경된 파일62개의 추가작업 그리고 57개의 파일을 삭제
  1. 62 57
      rtl/objpas/classes/classes.inc

+ 62 - 57
rtl/objpas/classes/classes.inc

@@ -334,68 +334,73 @@ procedure TThread.Synchronize(AMethod: TThreadMethod);
     TThread.Synchronize(self,AMethod);
     TThread.Synchronize(self,AMethod);
   end;
   end;
 
 
+Function PopThreadQueueHead : TThread.PThreadQueueEntry;
+
+begin
+  Result:=ThreadQueueHead;
+  if (Result<>Nil) then
+    begin
+    System.EnterCriticalSection(ThreadQueueLock);
+    try
+      Result:=ThreadQueueHead;
+      if Result<>Nil then
+        ThreadQueueHead:=ThreadQueueHead^.Next;
+    finally
+      System.LeaveCriticalSection(ThreadQueueLock);
+    end;
+    end;
+end;
 
 
 function CheckSynchronize(timeout : longint=0) : boolean;
 function CheckSynchronize(timeout : longint=0) : boolean;
-  { assumes being called from GUI thread }
-  var
-    exceptobj: Exception;
-    tmpentry: TThread.PThreadQueueEntry;
-  begin
-    result:=false;
-    { first sanity check }
-    if Not IsMultiThread then
-      Exit
-    { second sanity check }
-    else if GetCurrentThreadID<>MainThreadID then
-      raise EThread.CreateFmt(SCheckSynchronizeError,[GetCurrentThreadID])
+
+{ assumes being called from GUI thread }
+var
+  ExceptObj: Exception;
+  tmpentry: TThread.PThreadQueueEntry;
+
+begin
+  result:=false;
+  { first sanity check }
+  if Not IsMultiThread then
+    Exit
+  { second sanity check }
+  else if GetCurrentThreadID<>MainThreadID then
+    raise EThread.CreateFmt(SCheckSynchronizeError,[GetCurrentThreadID]);
+  if timeout>0 then
+    RtlEventWaitFor(SynchronizeTimeoutEvent,timeout)
+  else
+    RtlEventResetEvent(SynchronizeTimeoutEvent);
+  tmpentry := PopThreadQueueHead;
+  while Assigned(tmpentry) do
+    begin
+    { step 1: update the list }
+    if not Assigned(ThreadQueueHead) then
+      ThreadQueueTail := Nil;
+    { step 2: execute the method }
+    exceptobj := Nil;
+    try
+      ExecuteThreadQueueEntry(tmpentry);
+    except
+      exceptobj := Exception(AcquireExceptionObject);
+    end;
+    { step 3: error handling and cleanup }
+    if Assigned(tmpentry^.SyncEvent) then
+      begin
+      { for Synchronize entries we pass back the Exception and trigger
+        the event that Synchronize waits in }
+      tmpentry^.Exception := exceptobj;
+      RtlEventSetEvent(tmpentry^.SyncEvent)
+      end
     else
     else
       begin
       begin
-        if timeout>0 then
-          begin
-            RtlEventWaitFor(SynchronizeTimeoutEvent,timeout);
-          end
-         else
-           RtlEventResetEvent(SynchronizeTimeoutEvent);
-
-        System.EnterCriticalSection(ThreadQueueLock);
-        try
-          { Note: we don't need to pay attention to recursive calls to
-                  Synchronize as those calls will be executed in the context of
-                  the GUI thread and thus will be executed immediatly instead of
-                  queuing them }
-          while Assigned(ThreadQueueHead) do begin
-            { step 1: update the list }
-            tmpentry := ThreadQueueHead;
-            ThreadQueueHead := ThreadQueueHead^.Next;
-            if not Assigned(ThreadQueueHead) then
-              ThreadQueueTail := Nil;
-
-            { step 2: execute the method }
-            exceptobj := Nil;
-            try
-              ExecuteThreadQueueEntry(tmpentry);
-            except
-              exceptobj := Exception(AcquireExceptionObject);
-            end;
-
-            { step 3: error handling and cleanup }
-            if Assigned(tmpentry^.SyncEvent) then begin
-              { for Synchronize entries we pass back the Exception and trigger
-                the event that Synchronize waits in }
-              tmpentry^.Exception := exceptobj;
-              RtlEventSetEvent(tmpentry^.SyncEvent)
-            end else begin
-              { for Queue entries we dispose the entry and raise the exception }
-              Dispose(tmpentry);
-              if Assigned(exceptobj) then
-                raise exceptobj;
-            end;
-          end;
-        finally
-          System.LeaveCriticalSection(ThreadQueueLock);
-        end;
+      { for Queue entries we dispose the entry and raise the exception }
+      Dispose(tmpentry);
+      if Assigned(exceptobj) then
+        raise exceptobj;
       end;
       end;
-  end;
+    tmpentry := PopThreadQueueHead;
+    end;
+end;
 
 
 
 
 class function TThread.GetCurrentThread: TThread;
 class function TThread.GetCurrentThread: TThread;