Использование Delphi
猛禽[Ментальная студия]
http://mental.mentsu.com
之五(大结局)
Установите флажок «CheckSynchronize», а затем нажмите «CheckSynchronize».
функция CheckSynchronize(Timeout: Integer = 0): Boolean;
вар
СинкПРок: ПсинкПрок;
ЛокальныйСинкСписок: TList;
начинать
если GetCurrentThreadID <> MainThreadID, то
поднять EThread.CreateResFmt(@SCheckSynchronizeError, [GetCurrentThreadID]);
если тайм-аут > 0, то
WaitForSyncEvent (Тайм-аут)
еще
Ресетсинкэвент;
LocalSyncList: = ноль;
EnterCriticalSection (ThreadLock);
пытаться
Integer(LocalSyncList) := InterlockedExchange(Integer(SyncList), Integer(LocalSyncList));
пытаться
Результат:= (LocalSyncList <> ноль) и (LocalSyncList.Count > 0);
если Результат, то
начинать
в то время как LocalSyncList.Count > 0 делать
начинать
SyncProc := LocalSyncList[0];
LocalSyncList.Delete(0);
LeaveCriticalSection (ThreadLock);
пытаться
пытаться
SyncProc.SyncRec.FMethod;
кроме
SyncProc.SyncRec.FSynchronizeException: = AcquireExceptionObject;
конец;
окончательно
EnterCriticalSection (ThreadLock);
конец;
SetEvent(SyncProc.сигнал);
конец;
конец;
окончательно
ЛокальныйСинкЛист.Бесплатно;
конец;
окончательно
LeaveCriticalSection (ThreadLock);
конец;
конец;
首先,这个方法必须在主线程中被调用(如前面通过消息传递到主线程),否则就抛出异常。
Функция ResetSyncEvent (它与前面SetSyncEvent) Для Linux установите флажок «CheckSynchronize», для Windows установите флажок «CheckSynchronize».
Список SyncList доступен для скачивания:所有未被执行的同步方法的。因为主线程只有一个,而子线程可能有很多个,当多个子线程同时调用同步方法时,主线程可能一时无法处理,所以需要一个列表来记录它们。
在这里用一个局部变量来交换SyncList,这里用的也是一个原语:I nterlockedExchange также доступен для использования в SyncList.
Используйте LocalSyncList, чтобы получить доступ к файлу LocalSyncList.同步方法调用。最后把处理完的LocalSyncList释放掉, 退出临界区。
再来看对同步方法的处理:首先是从列表中移出 (取出并从列表中删除)第一个同步方法调用数据。然后退出临界区(原因当然也是为了防止死锁)。
接着就是真正的调用同步方法了。
如果同步方法中出现异常,将被捕获后存入同步方法数据记录中。
重新进入临界区后,调用SetEvent通知调用线程,同步方法执行完成了(详见Синхронизация и WaitForSingleObject.
至此, Synchronize 介绍完成。
最后来说一下WaitFor,它的功能就是等待线程执行结束。其代码如下:
функция TThread.WaitFor: LongWord;
вар
H: массив [0..1] из THandle;
WaitResult: Кардинал;
Сообщение: ТМСг;
начинать
H[0] := FHandle;
если GetCurrentThreadID = MainThreadID, то
начинать
ОжиданиеРезультат: = 0;
H[1] := SyncEvent;
повторить
{ Это предотвращает потенциальную взаимоблокировку, если фоновый поток
отправляет SendMessage в поток переднего плана }
если WaitResult = WAIT_OBJECT_0 + 2, то
PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
WaitResult:= MsgWaitForMultipleObjects(2, H, False, 1000, QS_SENDMESSAGE);
CheckThreadError(WaitResult <> WAIT_FAILED);
если WaitResult = WAIT_OBJECT_0 + 1, то
Проверить синхронизацию;
пока WaitResult = WAIT_OBJECT_0;
конец еще WaitForSingleObject(H[0], INFINITE);
CheckThreadError(GetExitCodeThread(H[0], Результат));
конец;
如果不是在主线程中执行WaitFor的话,很简单, 只要调用WaitForS IngleObject, Handle, Signaled, Signaled.
如果是在主线程中执行WaitFor则比较麻烦。首先要在Hand le数组中增加一个SyncEvent,然后循环等待, 直到线程结Используйте MsgWaitForMultipleObjects в формате WAIT_OBJECT_0, MSDN 中关于 и API的说明).
在循环等待中作如下处理:如果有消息发生,则通过PeekMes мудрец取出此消息(但并不把它从消息循环中移除),然后调用M Функции sgWaitForMultipleObjects и Handle, SyncEvent и Signaled, а также функции Signaled и др.听消息(QS_SENDMESSAGE参数,详见MSDN中关于)此API的说明)。可以把此API当作一个可以同时等待多个 Хан dle — WaitForSingleObject, SyncEvent — SetEvent (WAIT_OBJECT_0). + 1), установите флажок «CheckSynchronize» и нажмите «CheckSynchronize».
为什么在主线程中调用WaitFor必须用MsgWaitForMultipleObjects,而不能用WaitForSingleObject имеет функцию «Выполнить» или «Execute».可能调用Synchronize处理同步方法,而同步方法是在主线程中执行的, 如果用WaitForSin gleObject等待的话,则主线程在这里被挂起,同步方法无法执行,导致线程也被挂起,于是发生死锁。
而改用WaitForMultipleObjects则没有这个问题。首先,它的第三个参数为False,表示只Обработчик Handle, SyncEvent, Signaled и Signaled, QS_SEND MESSAGE是因为Synchronize是通过消息传到主线程来的,所以还要防止消息被阻塞。这样,当线程中调用Synchronize时, 主线程就会被唤醒并处理同步调用, 在调用完成后继续进入挂起等待状态, 直到线程结束.
Связанные файлы TThread могут быть использованы в качестве примера:
1、线程类的线程必须按正常的方式结束, 即Execute执行结束,所以在其中的代码中必须在适当的地方加入足够多的对T прекращенный标志的判断,并及时退出。如果必须要“立Используйте API, RTL и API.
2. Используйте функцию VCL, которая позволяет синхронизировать синхронизацию и синхронизацию.
3、 线程共享数据的访问应该用临界区进行保护(当然用Synchronize也行).。
4. Нажмите «Событие», «Приостановить/возобновить».
5. 当在多线程应用中使用多种线程同步方式时, 一定要小心防止出现死锁。
6. 等待线程结束要用WaitFor方法.
01-03 декабря
(终于续完了)