打印本文 打印本文 关闭窗口 关闭窗口
Delphi中的线程类--之(5,大结局)
作者:武汉SEO闵涛  文章来源:敏韬网  点击数1519  更新时间:2009/4/23 18:35:45  文章录入:mintao  责任编辑:mintao

Delphi中的线程类

 

猛禽[Mental Studio]

http://mental.mentsu.com

 

之五(大结局)

回到前面CheckSynchronize,见下面的代码:

function CheckSynchronize(Timeout: Integer = 0): Boolean;

var

  SyncProc: PSyncProc;

  LocalSyncList: TList;

begin

  if GetCurrentThreadID <> MainThreadID then

    raise EThread.CreateResFmt(@SCheckSynchronizeError, [GetCurrentThreadID]);

  if Timeout > 0 then

    WaitForSyncEvent(Timeout)

  else

    ResetSyncEvent;

  LocalSyncList := nil;

  EnterCriticalSection(ThreadLock);

  try

    Integer(LocalSyncList) := InterlockedExchange(Integer(SyncList), Integer(LocalSyncList));

    try

      Result := (LocalSyncList <> nil) and (LocalSyncList.Count > 0);

      if Result then

      begin

        while LocalSyncList.Count > 0 do

        begin

          SyncProc := LocalSyncList[0];

          LocalSyncList.Delete(0);

          LeaveCriticalSection(ThreadLock);

          try

            try

              SyncProc.SyncRec.FMethod;

            except

              SyncProc.SyncRec.FSynchronizeException := AcquireExceptionObject;

            end;

          finally

            EnterCriticalSection(ThreadLock);

          end;

          SetEvent(SyncProc.signal);

        end;

      end;

    finally

      LocalSyncList.Free;

    end;

  finally

    LeaveCriticalSection(ThreadLock);

  end;

end;

首先,这个方法必须在主线程中被调用(如前面通过消息传递到主线程),否则就抛出异常。

接下来调用ResetSyncEvent(它与前面SetSyncEvent对应的,之所以不考虑WaitForSyncEvent的情况,是因为只有在Linux版下才会调用带参数的CheckSynchronize,Windows版下都是调用默认参数0的CheckSynchronize)。

现在可以看出SyncList的用途了:它是用于记录所有未被执行的同步方法的。因为主线程只有一个,而子线程可能有很多个,当多个子线程同时调用同步方法时,主线程可能一时无法处理,所以需要一个列表来记录它们。

在这里用一个局部变量LocalSyncList来交换SyncList,这里用的也是一个原语:InterlockedExchange。同样,这里也是用临界区将对SyncList的访问保护起来。

只要LocalSyncList不为空,则通过一个循环来依次处理累积的所有同步方法调用。最后把处理完的LocalSyncList释放掉,退出临界区。

再来看对同步方法的处理:首先是从列表中移出(取出并从列表中删除)第一个同步方法调用数据。然后退出临界区(原因当然也是为了防止死锁)。

[1] [2]  下一页

打印本文 打印本文 关闭窗口 关闭窗口