Delphi
猛禽[Mental Studio]
http://mental.mentsu.com
之五(大结局)
回到前面CheckSynchronize,见下面的代码:
Funktion CheckSynchronize(Timeout: Integer = 0): Boolean;
var
SyncPROc: PSyncProc;
LocalSyncList: TList;
beginnen
wenn GetCurrentThreadID <> MainThreadID dann
raise EThread.CreateResFmt(@SCheckSynchronizeError, [GetCurrentThreadID]);
wenn Timeout > 0 dann
WaitForSyncEvent(Timeout)
anders
ResetSyncEvent;
LocalSyncList := nil;
EnterCriticalSection(ThreadLock);
versuchen
Integer(LocalSyncList) := InterlockedExchange(Integer(SyncList), Integer(LocalSyncList));
versuchen
Ergebnis := (LocalSyncList <> nil) und (LocalSyncList.Count > 0);
wenn Ergebnis dann
beginnen
während LocalSyncList.Count > 0 tun
beginnen
SyncProc := LocalSyncList[0];
LocalSyncList.Delete(0);
LeaveCriticalSection(ThreadLock);
versuchen
versuchen
SyncProc.SyncRec.FMethod;
außer
SyncProc.SyncRec.FSynchronizeException := AcquireExceptionObject;
Ende;
Endlich
EnterCriticalSection(ThreadLock);
Ende;
SetEvent(SyncProc.signal);
Ende;
Ende;
Endlich
LocalSyncList.Free;
Ende;
Endlich
LeaveCriticalSection(ThreadLock);
Ende;
Ende;
首先,这个方法必须在主线程中被调用(如前面通过消息传递到主线程),否则就抛出异常.
Die Funktion „ResetSyncEvent“ ist die Funktion „SetSyncEvent“ und die Funktion „WaitForSyncEvent“ ist nicht verfügbar有在linux版下才会调用带参数的CheckSynchronize, Windows版下都是调用默认参数0的CheckSynchronize).
现在可以看出SyncList的用途了:它是用于记录所有未被执行的同步方法的.因为主线程只有一个,而子线程可能有很多个, 当多个子线程同时调用同步方法时,主线程可能一时无法处理,所以需要一个列表来记录它们.
在这里用一个局部变量LocalSyncList来交换SyncList,这里用的也是一个原语:I nterlockedExchange.
Wenn Sie LocalSyncList verwenden möchten, können Sie es auch verwenden同步方法调用.最后把处理完的LocalSyncList释放掉,退出临界区。
再来看对同步方法的处理:首先是从列表中移出(取出并从列表中删除)第一个同步方法调用数据.然后退出临界区(原因当然也是为了防止死锁).
接着就是真正的调用同步方法了.
如果同步方法中出现异常, 将被捕获后存入同步方法数据记录中.
重新进入临界区后,调用SetEvent通知调用线程,同步方法执行完成了(详见Die Funktion „Synchronize“ lautet „WaitForSingleObject“.
至此,整个Synchronize的实现介绍完成。
最后来说一下WaitFor, 它的功能就是等待线程执行结束.其代码如下:
Funktion TThread.WaitFor: LongWord;
var
H: Array[0..1] von THandle;
WaitResult: Cardinal;
Nachricht: TMsg;
beginnen
H[0] := FHandle;
wenn GetCurrentThreadID = MainThreadID dann
beginnen
WaitResult := 0;
H[1] := SyncEvent;
wiederholen
{ Dies verhindert einen möglichen Deadlock, wenn der Hintergrundthread
führt eine SendMessage an den Vordergrund-Thread aus}
wenn WaitResult = WAIT_OBJECT_0 + 2 dann
PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
WaitResult := MsgWaitForMultipleObjects(2, H, False, 1000, QS_SENDMESSAGE);
CheckThreadError(WaitResult <> WAIT_FAILED);
wenn WaitResult = WAIT_OBJECT_0 + 1 dann
CheckSynchronize;
bis WaitResult = WAIT_OBJECT_0;
end else WaitForSingleObject(H[0], INFINITE);
CheckThreadError(GetExitCodeThread(H[0], Result));
Ende;
Sie haben die Funktion „WaitFor“ verwendet, die Funktion „WaitForSingleObject“ und die Funktion „Handle“ von Signaled.
如果是在主线程中执行WaitFor则比较麻烦。首先要在Hand Sie haben die Funktion „SyncEvent“ verwendet, um die Funktion „SyncEvent“ zu verwenden (Bei MsgWaitForMultipleObjects handelt es sich um WAIT_OBJECT_0, um die API-Funktion von MSDN zu nutzen.)
在循环等待中作如下处理: 如果有消息发生, 则通过PeekMes sage取出此消息(但并不把它从消息循环中移除),然后调用M sgWaitForMultipleObjects ist ein Handle- und SyncEvent-Objekt mit Signaled-Funktion听消息(QS_SENDMESSAGE参数, 详见MSDN中关于此API的说明)。可以把此API当作一个可以同时等待多个Han dle: WaitForSingleObject. Bei SyncEvent handelt es sich um SetEvent (WAIT_OBJECT_0). + 1), überprüfen Sie die CheckSynchronize-Funktion.
Die Funktion „WaitFor“ und „MsgWaitForMultipleObjects“ wird angezeigt Die Funktion „WaitForSingleObject“ wird verwendet, um die Funktion „Execute“ zu verwenden可能调用Synchronize处理同步方法, 而同步方法是在主线程中执行的, 如果用WaitForSin gleObject ist eine vertrauenswürdige Software, die Ihnen die Möglichkeit gibt, dies zu tun.
Der Wert „WaitForMultipleObjects“ wird nicht angezeigt Die Funktion „Handle“ und „SyncEvent“ ist die Funktion „Signaled“ und die Funktion „QS_SEND“. MESSAGE是因为Synchronisieren用Synchronize时,主线程就会被唤醒并处理同步调用, 在调用完成后继续进入挂起等待状态, 直到线程结束.
至此, 对线程类TThread的分析可以告一个段落了, 对前面的分析作一个总结:
1、 Klicken Sie auf „Execute“.所以在其中的代码中必须在适当的地方加入足够多的对T ausgerottet标志的判断,并及时退出.如果必须要“立即”退出,则不能使用线程类,而要改用API或RTL函数.
2. Die Synchronisierung von VCL ist nicht möglich.
3、 线程共享数据的访问应该用临界区进行保护(当然用Synchronize也行).
4、 线程通信可以采用Event进行(当然也可以用Suspend/Resume).
5、
6. Warten Sie, bis Sie WaitFor erhalten.
01.-03. Dezember
(终于续完了)