zoukankan      html  css  js  c++  java
  • Delphi写的DLL,OCX中多线程一个同步问题

    Delphi写的DLL,OCX中如果使用了TThread.Synchronze(Proc),可能导致线程死锁,原因是无法唤醒EXE中主线程,

    Synchronze并不会进入EXE主线程消息队列.

    下面的程序自动解决此问题,只需要加入DLL,OCX工程文件中,在DLL,OCX中便可以使用TThread.Synchronze(Proc)了,无需再写一行代码。

    //解决Delphi编译的DLL,OCX文件中的线程调用 TThread.Synchronize后挂起无法再激活问题
    //调用了TThread.Synchronize函数的所有工程请包含此文件
    //仅需将此单元包含到工程文件即可
    
    unit Lib.Common.DLLThread;
    
    interface
    
    
    implementation
    
    uses Classes, Windows, Messages;
    
    type
    
      { TDLLSystemController }
    
      TDLLSystemController = class
      private
        FHandle: HWND;
        FPrevWakeMainThread: TNotifyEvent;
        procedure WakeMainThread(Sender: TObject);
        procedure HookSynchronizeWakeup;
        procedure UnhookSynchronizeWakeup;
      protected
        procedure WndProc(var Message: TMessage);
      public
        constructor Create;
        destructor Destroy; override;
      end;
    
    var
      FDLLController:TDLLSystemController;
    
    { TDLLSystemController }
    
    constructor TDLLSystemController.Create;
    begin
      inherited;
      if IsLibrary then
      begin
        FHandle := AllocateHWnd(WndProc);
        HookSynchronizeWakeup;
      end;
    end;
    
    destructor TDLLSystemController.Destroy;
    begin
      if IsLibrary then
      begin
        DeallocateHWnd(FHandle);
        UnhookSynchronizeWakeup;
      end;
      inherited;
    end;
    
    procedure TDLLSystemController.WndProc(var Message: TMessage);
    begin
      case Message.Msg of
        WM_NULL: CheckSynchronize;
      else
        Message.Result := DefWindowProc(FHandle, Message.Msg, Message.wParam, Message.lParam);
      end;
    end;
    
    procedure TDLLSystemController.WakeMainThread(Sender: TObject);
    begin
      PostMessage(FHandle, WM_NULL, 0, 0);
    end;
    
    procedure TDLLSystemController.HookSynchronizeWakeup;
    begin
      FPrevWakeMainThread := Classes.WakeMainThread;
      Classes.WakeMainThread := WakeMainThread;
    end;
    
    procedure TDLLSystemController.UnhookSynchronizeWakeup;
    begin
      Classes.WakeMainThread := FPrevWakeMainThread;
    end;
    
    
    initialization
      if IsLibrary then FDLLController := TDLLSystemController.Create
        else FDLLController:=nil;
    finalization
      if Assigned(FDLLController) then FDLLController.Free;
    end.
  • 相关阅读:
    linux环境下的时间编程
    golang1.13中重要的新特新
    vs2019+cmake实现Linux远程开发
    现代c++与模板元编程
    一个commit引发的思考
    golang中判断两个slice是否相等
    c++性能测试工具:计算时间复杂度
    c++性能测试工具:google benchmark入门(二)
    使用vs2019进行Linux远程开发
    智能指针和二叉树(3):图解查找和删除
  • 原文地址:https://www.cnblogs.com/hezihang/p/3965179.html
Copyright © 2011-2022 走看看