1. 程式人生 > >原創 DLL編寫經驗總結(一)使DLL支援多執行緒

原創 DLL編寫經驗總結(一)使DLL支援多執行緒

最近用Delphi編寫DLL比較多,總結幾條經驗方便以後回顧。

需求背景:DLL介面自身是向主調方提供服務,考慮到主調方的不定性以及響應速度問題,需要支援多執行緒。

實現思路:DLL在初次載入或者被喚醒的時候會呼叫DLLMain函式(DelphiMain函式頭已被隱藏,實際上就是主檔案中的Begin End),觸發DLL_Process_Attach事件。可用全域性變數DLLProc來處理觸發的事件所呼叫的函式。

DLL在退出的時候會呼叫DLLMain函式(DelphiMain函式頭已被隱藏,實際上就是主檔案中的Begin End),觸發DLL_Process_Detach事件。可用全域性變數ExitProc

來處理觸發的事件所呼叫的函式。

Delphi原始碼如下:

var

  OldExitProc:pointer;


begin

    DLLProc:[email protected];//由於DLLProc原事件已經執行完成,此處可以不再儲存原事件

    MyDLLHandler(DLL_Process_Attach);//執行自定義方法

 

    OldExitProc:=ExitProc;//暫存退出後處理函式地址

    ExitProc:[email protected]; //讓系統呼叫自定義函式處理事情,在MyExitProc中需要賦值回來。

end.

 

為了限制不同時執行某些關鍵區域,使用Delphi Windows下的CriticalSection

在DLL對映時建立,在介面中運用Enter、Leave,在退出時銷燬

var
  FSection: TRTLCriticalSection;//定義一個關鍵區域用於執行緒互斥執行
//關鍵區域進出
procedure Enter(OutType:string);
begin
  _log('Enter FSection',OutType);
  EnterCriticalSection(FSection);
end;

procedure Leave(OutType:string);
begin
   _log('Leave FSection',OutType);
   LeaveCriticalSection(FSection);
end;
//關鍵區域使用
procedure MyDLLHandler(Reason: integer);
begin
  case Reason of
    DLL_Process_Attach: //整個DLL的初始化程式碼
      begin
          _log('DLL_Process_Attach', 'FSection');
          InitializeCriticalSection(FSection);
      end;
    DLL_Process_Detach: //整個DLL的善後程式
      begin
        DeleteCriticalSection(FSection);
        _log('DLL_Process_Detach', 'FSection');
      end;
    DLL_Thread_Attach: //當主叫端開始一個Thread時
      begin
        _log('DLL_Thread_Attach', 'FSection');
        StartMyThreadsAndWaitBegin();
      end;
    DLL_Thread_Detach: //當主叫端終止一個Thread時
      begin
        _log('DLL_Thread_Detach', 'FSection');
        StopMyThreadsAndWaitEnd();
      end;
  end;
end;
procedure MyExitProc;
begin
  _log('MyExitProc','FSection');
  ExitProc:=OldExitProc;//恢復退出的事件
end;

procedure StartMyThreadsAndWaitBegin();
begin
  _log('StartMyThreadsAndWaitBegin','FSection');
  Exit;
end;

procedure StopMyThreadsAndWaitEnd();
begin
  _log('StopMyThreadsAndWaitEnd','FSection');
  Exit;
end;

關鍵區域在介面中運用舉例:

{
   created by: JustinYang 2016-09-23
   function: 托盤解綁
   Param in: Ahandle窗體控制代碼, serverIP 訪問伺服器IP,serverPort 伺服器埠,s_TrayID 托盤編號,i_TrayRFID 托盤RFID
   Param Out: 整型 -1 網路異常;-2 托盤編號長度不對; -3 RFID大小異常; 1 解綁成功 0 解綁不成功 
}
function upFreeTray(AHandle: THandle; serverIP: PChar; serverPort: integer; s_TrayID:PChar; i_TrayRFID:Int64): integer; export; stdcall;
var
  p_serverIP: string;
  P_serverPort,j: Integer;
  tOld,tNew:TDateTime;
  trayID:string;
  trayRFID:Int64;
  hw:Integer;
begin
  try
    try
      Enter('FSection');

      j:=-1;
      result:=j;
      _log(' IP:'+serverIP+' Port:'+IntToStr(serverPort),'upFreeTray');
      if Length(string(s_TrayID)) <3 then s_TrayID :='';
      _log(' Begin upFreeTray IP:'+serverIP+' Port:'+IntToStr(serverPort)+' Tray:'+IntToStr(i_TrayRFID)+':'+s_TrayID+' at '+DateTimeToStr(Now),'upFreeTray');     

      CoInitialize(nil);
      Application.handle := AHandle;
      
      trayID:=string(s_TrayID);
      trayRFID:=i_TrayRFID;
      if (Trim(trayID)='') and (trayRFID <= 0) then
      begin
        _log(' End upFreeTray '+IntToStr(trayRFID)+':'+trayID+'  at '+ DateTimeToStr(Now) + ' result:'+IntToStr(j),'upFreeTray');
        result:=0;
        Exit;
      end;

      DllDataModule := TDllDataModule.Create(Application);


      p_serverIP := string(serverIP);
      if serverPort <= 0 then
        P_serverPort := 8095
      else
        P_serverPort := serverPort;
      DllDataModule.Channel.Host := string(p_serverIP);
      DllDataModule.Channel.Port := P_serverPort;
    except
      on e:Exception do
      begin
          j := -1;//網路連線失敗
          _log('When dll access network occours:'+e.Message,'upFreeTray');
          Exit;
      end;
    end;
    try
       j := ((DllDataModule.RemoteService as INewService).upFreeTray(trayID, trayRFID));
       if j > 0 then j := 1;
    except
      on e:Exception do
      begin
        j:=-4;
        _log('When dll access server occours:'+e.Message,'upFreeTray');
        Exit;
      end;
    end;
  finally
    DllDataModule.free;
    result:=j;
    _log(' End upFreeTray '+IntToStr(i_TrayRFID)+' '+s_TrayID+'  at '+ DateTimeToStr(Now) + ' result:'+IntToStr(j),'upFreeTray');
    CoUninitialize;
    Leave('FSection');
  end;
end;

相關推薦

原創 DLL編寫經驗總結使DLL支援執行

最近用Delphi編寫DLL比較多,總結幾條經驗方便以後回顧。需求背景:DLL介面自身是向主調方提供服務,考慮到主調方的不定性以及響應速度問題,需要支援多執行緒。實現思路:DLL在初次載入或者被喚醒的時候會呼叫DLLMain函式(Delphi的Main函式頭已被隱藏,實際上就

Redis面試題: Redis到底是執行還是單執行

0. redis單執行緒問題     單執行緒指的是網路請求模組使用了一個執行緒(所以不需考慮併發安全性),即一個執行緒處理所有網路請求,其他模組仍用了多個執行緒。   1

C++11併發程式設計——初始C++11執行

1 前言   C++11標準在標準庫中為多執行緒提供了元件,這意味著使用C++編寫與平臺無關的多執行緒程式成為可能,而C++程式的可移植性也得到了有力的保證。   在之前我們主要使用的多執行緒庫要麼

java_web項目開發經驗總結

從數據 簡單 處理 開發 事務 傳輸 記錄 承載 基礎上   web項目就像一個動態的記事本,功能很強大,你最初的項目功能調研越給力,項目所能發揮的作用也就越給力。這是因為web網絡的強聯系性,大家都可以通過訪問到自己想要訪問的頁面,頁面裏既可以承載信息,也可以承載做事情的

HTTP介面自動化經驗總結介面自動化簡述

講介面自動化之前,先說說介面測試的優勢。      以下是我總結的幾點。 介面測試位於功能測試前,發現bug早修改早成本低。 介面測試的引數會比開發的引數更豐富,得到的結果更快更多。 能發現大部分介面未校驗的引數,省去我們功能測試輸入太多數值。

2015異常問題解決方案經驗總結

1.     could not find java.dll C:\Users\admin>java Error: Registry key 'Software\JavaSoft\JavaRuntime has value '1.6', but '1.8' is r

美團外賣開放平臺對接經驗總結

兩個月的時間,在除官方文件之外的資源極其匱乏的條件下,專案組群策群力完成了美團和餓了麼的外賣開放平臺對接,在這裡對團隊成員表示感謝,也把專案中填過的坑,淌過的河分享給大家。這注定是一篇受眾極少的文章,但是希望能夠對需要的人有所幫助。 如果能回到兩個月前,我會告訴剛剛開始開發這個專案的團隊,開發之

Netty 入門:基本元件與執行模型

  Netty 的學習內容主要是圍繞 TCP 和 Java NIO 這兩個點展開的,後文中所有的內容如果沒有特殊說明,那麼所指的內容都是與這兩點相關的。由於 Netty 是基於 Java NIO 的 API 之上構建的網路通訊框架,Java NIO 中的幾個元件,都能在 Netty 中找到對應的封裝。下面我們

Windows執行最簡單的執行建立

一段最簡單的多執行緒建立程式碼如下: #include <stdio.h> #include <process.h> #include <Windows.h> #define THREAD_NUM 5 unsigned int __stdca

python學習總結,第一個python程序的編寫

程序代碼 spa 編碼 結構 編輯 下載地址 utf 修改編碼 general 1. python是一種解釋性,編譯型,互動型的語言,面向對象,動態數據類型的高級程序設計語言。 1.1 交互式:意味著可以在一個提示符直接交互執行你寫的程序。 1.2 解釋型:意味著開發過程中

HTTP介面自動化經驗總結Okhttp3 介面測試用例編寫

經過前面幾次的分享,我們已經有了方法和結果,那麼這篇文章我們就來寫測試用例。 首先我們新建一個TestNG class,名字為APITest,繼承我們的依賴方法DependeicesMethod 1.get介面測試 //測試Get方法,其餘校驗請自行新增 @Test

QT 總結1.某位設1或0 2.載入dll、lib庫 3.char * 轉換為 wchar_t * 4.textBrowser 顯示亂碼 追加 5.checkBox的使

今天寫小程式遇到的問題,做個小總結: 1.如何對某一位置0或者置1? 寫成巨集,方便移植 #define setbit(x,y) x|=(1<<y) //將X的第Y位置1 #define clrbit(x,y) x&=~(1<<y) //將

去BAT,你應該要看看的面試經驗總結

unique lock lose 單鏈表 一個數 協議頭 art 進制 操作系統原理 來源微信公眾號『easyserverdev』 http://mp.weixin.qq.com/s/UZljzFMjobo1wzCguY7NDg 說下我的面試經驗吧,都是親身經歷,

項目優化經驗分享數據自己主動匹配

als 主動 options option reg shee total tomat 功能 從今天開始。我將和大家分享一下近期經手項目的優化經驗。今天我們分享的內容是:自己主動匹配! 引言: 輸入框數據自己主動匹配大家應該非常熟悉,當我們在使用百度或go

文檔總結——文檔的概述

理解 需要 軟件需求 是否 研究 strong 開發項目 問題 項目開發 寫完文檔後,本來想寫一篇具體的文檔的總結的,後來看大家都寫的具體文檔總結,於是我就想:我還是寫一些跟大家不一樣的東西吧。 所以,我就說說我對各個文檔的宏觀理解吧。

salesforce零基礎學習七十二項目中的零碎知識點小總結

gin 不同 grant dmi ima -m ron 角色 com 項目終於告一段落,雖然比較苦逼,不過也學到了好多知識,總結一下,以後當作參考。 一.visualforce標簽中使用html相關的屬性使用 曾經看文檔沒有看得仔細,導致開發的時候走了一些彎路。還好得到

HDMI調試經驗分享—— 基於KC705的example實現

alt 如果 追蹤 分享 生成 必須 還需要 pro 註意 在KC705的平臺上,實現HDMI的example有兩個,xapp1287,xapp1291。其中1291偏復雜。 因為我沒有HDCP的license,使用xapp1287的tcl生成

OpenGL在MFC中的使用總結——基本框架

palette 接受 white 要求 無效 結構 del 一次 是你 項目中要畫3D顯示的模型,於是要用到OpenGL,加上是在MFC中,並且是在MFC中的ActiveX中使用。再並且鑒於他們程序主框架的設定。常規的方法還不一定能實現。所以還是查過不少資料,在此一一總

操作系統基礎知識總結

一個 快速 會有 處理死鎖 b2c fcm 死鎖 空間 存儲系統 1. 進程和線程的區別 進程 進程,即正在運行的程序,程序從硬盤載入到內存就變成進程。進程是資源的擁有者,每個進程都擁有著自己的內存空間與多個線程。 線程 線程是指令的執行者,是計算機執行指令的基本單元,一個

react native 知識點總結

修改 ltp 組件 改變 set 覆蓋 sta 一個 個數 一、關於react native 版本的升級 參照文檔:http://reactnative.cn/docs/0.45/upgrading.html react-native -v