Delphi adalah sebuah aplikasi yang sangat berguna
猛禽[Studio Mental]
http://mental.mentu.com
之五(大结局)
回到前面CheckSynchronize:
fungsi CheckSynchronize(Batas Waktu: Integer = 0): Boolean;
var
SinkronisasiPROc: PSyncProc;
Daftar Sinkronisasi Lokal: TList;
mulai
jika GetCurrentThreadID <> MainThreadID maka
naikkan EThread.CreateResFmt(@SCheckSynchronizeError, [GetCurrentThreadID]);
jika Batas Waktu > 0 maka
WaitForSyncEvent (Waktu Habis)
kalau tidak
Atur UlangSyncEvent;
Daftar Sinkronisasi Lokal := nihil;
EnterCriticalSection(ThreadLock);
mencoba
Integer(LocalSyncList) := InterlockedExchange(Integer(SyncList), Integer(LocalSyncList));
mencoba
Hasil := (LocalSyncList <> nihil) dan (LocalSyncList.Count > 0);
jika Hasil maka
mulai
sementara LocalSyncList.Count > 0 lakukan
mulai
SyncProc := Daftar Sinkronisasi Lokal[0];
LocalSyncList.Hapus(0);
TinggalkanCriticalSection(ThreadLock);
mencoba
mencoba
Metode SyncProc.SyncRec.FM;
kecuali
SyncProc.SyncRec.FSynchronizeException := AcquireExceptionObject;
akhir;
Akhirnya
EnterCriticalSection(ThreadLock);
akhir;
SetEvent(SyncProc.sinyal);
akhir;
akhir;
Akhirnya
Daftar Sinkronisasi Lokal.Gratis;
akhir;
Akhirnya
TinggalkanCriticalSection(ThreadLock);
akhir;
akhir;
首先,这个方法必须在主线程中被调用(如前面通过消息传递到主线程),否则就抛出异常。
ResetSyncEvent(它与前面SetSyncEvent对应的,之所以不考虑WaitForSyncEvent的情况,是因为只seperti Linux, CheckSynchronize, Windows, CheckSynchronize, dan lainnya.
SyncList dan SyncList: SyncList所有未被执行的同步方法的。因为主线程只有一个,而子,,,,,,,,,,,,,,,,,,主线程可能一时无法处理,所以需要一个列表来记录它们。
在这里用一个局部变量LocalSyncList来交换SyncList,这里用的也是一个原语:I nterlockedExchange.
Daftar LocalSyncList同步方法调用。最后把处理完的LocalSyncList释放掉,退出临界区。
再来看对同步方法的处理:首先是从列表中移出(取出并从列表中删除)第一个同步方法调用数据。然后退出临界区(原因当然也是为了防止死锁)。
接着就是真正的调用同步方法了。
如果同步方法中出现异常,将被捕获后存入同步方法数据记录中。
重新进入临界区后,调用SetEvent通知调用线程,同步方法执行完成了(详见前面Sinkronisasi中的WaitForSingleObject调用)。
至此,整个Sinkronisasikan aplikasi.
最后来说一下WaitFor,它的功能就是等待线程执行结束。其代码如下:
fungsi TThread.WaitFor: LongWord;
var
H: array[0..1] dari Thandle;
TungguHasil: Kardinal;
Pesan: TM;
mulai
H[0] := FMenangani;
jika GetCurrentThreadID = MainThreadID maka
mulai
TungguHasil := 0;
H[1] := Acara Sinkronisasi;
mengulang
{ Ini mencegah potensi kebuntuan jika thread latar belakang
melakukan SendMessage ke thread latar depan }
jika WaitResult = WAIT_OBJECT_0 + 2 maka
PeekMessage(Pesan, 0, 0, 0, PM_NOREMOVE);
WaitResult := MsgWaitForMultipleObjects(2, H, False, 1000, QS_SENDMESSAGE);
CheckThreadError(WaitResult <> WAIT_FAILED);
jika WaitResult = WAIT_OBJECT_0 + 1 maka
Periksa Sinkronisasi;
sampai WaitResult = WAIT_OBJECT_0;
akhiri yang lain WaitForSingleObject(H[0], INFINITE);
CheckThreadError(GetExitCodeThread(H[0], Hasil));
akhir;
如果不是在主线程中执行WaitFor的话,很简单,只要调用WaitForSingleObject等待此线程的Handle为Signaled状态即可。
如果是在主线程中执行WaitFor则比较麻烦。首先要在Hand le SyncEvent, aplikasi SyncEvent, dan lainnya ada di MsgWaitForMultipleObjects, WAIT_OBJECT_0, dan MSDN, serta API lainnya.
PeekMes sage dalam bahasa inggris sage sgWaitForMultipleObjects来等待线程Handle或SyncEvent出现Signaled状态,同时监Han dle的WaitForSingleObject。如果是SyncEvent被SetEvent(返回WAIT_OBJECT_0 + 1),则调用CheckSynchronize处理同步方法。
melalui aplikasi WaitFor dan MsgWaitForMultipleObjects, WaitForSingleObject等待线程结束呢?因为防止死锁。由于在线程函数Execute中可能调用Synchronize处理同步方法,而同步方法是在主线程中执行的,如果用WaitForSin gleObject adalah salah satu aplikasi yang paling berguna,同步方法无法执行,导致线程也被挂起,于是发生死锁。
而改用WaitForMultipleObjects则没有这个问题。首先,它的第三个参数为False,表示只要线程Handle或SyncEvent中只要有一个Signaled即可使主线程被唤醒,至于加上QS_SEND PESAN是因为Sinkronisasi是通过消息传到主线程来的,所以还要防止消息被阻塞。这样,当线程中调用Synchronize时,主线程就会被唤醒并处理同步调用,在调用完成后继续进入挂起等待状态,直到线程结束。
Berikut adalah beberapa contohnya:
1、 Eksekusi执行结束,所以在其中的代码中必须在适当的地方加入足够多的对T dimusnahkan标志的判断,并及时退出。如果必须要“立即”退出,则不能使用线程类,而要改用API或RTL函数。
2、 对可视VCL的访问要放在Synchronize中,通过消息传递到主线程中,由主线程处理。
3、 线程共享数据的访问应该用临界区进行保护(当然用 Sinkronisasi也行)。
4、 线程通信可以采用Acara进行(当然也可以用Tangguhkan/Lanjutkan)。
5、 当在多线程应用中使用多种线程同步方式时,一定要小心防止出现死锁。
6、 等待线程结束要用WaitFor方法。
01-03 Desember
(终于续完了)