麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

使用ADO,多線程訪問ACCESS數據庫的開發。

2019-11-18 18:37:07
字體:
來源:轉載
供稿:網友
 

本人最近正在進行呼叫中心的座席端和服務器軟件開發,座席端登錄部分是進行提取主機信息,然后使用SOCKET提交給遠程服務器,服務器再在后臺數據庫中進行查找信息,進行對比,看是否允許座席端主機登錄,因為我的電腦中無法安裝SQLSERVER,所以 ,后臺數據庫暫時使用access小型數據庫進行代替,到后期可以改為SQLSERVER數據庫,,我在后臺數據庫中使用了兩個表,使用WORKMARK字段將其相關聯,如果在第一個表中查找到信息以后馬上會進入第二個表中進行查找,如果第一個表中的信息符合,就返回個客戶第二個表中的信息,因為座席端主機有200多臺,為了防止幾臺主機同時進行驗證信息,引起沖突,我在服務器端建立多線程,利用線程進行后臺的查詢,以及查找結果的回傳,編寫成功后進行測試,發現當一個主機連接后可以測試成功,但是,當第二個或者以后的線程產生時,數據集在第一個表中可以查到正確的信息,但是進入第二個表中時,會發現按照正確的查找條件進行查找時,查到的信息都為NIL,而且經過跟蹤,發現,其實ADO已經找到了正確的信息,而且已經發送成功了,但是卻無法接收到,當時我在論壇中發表了一個帖子尋求幫助,原貼內容:http://expert.csdn.net/Expert/topic/1420/1420051.xml?temp=.3060114

有些朋友說可能ACCESS數據庫不提供多線程訪問,但是我聽說很多的論壇中好像都使用了ACCESS進行后臺線程的查找的。翻看MSDN中關于COM的說明:發現我的線程中竟然缺少最重要的兩個函數過程

CoInitialize( nil );凡是訪問com對象都應該使用。線程的關閉時應該使用CoUnInitialize;否則ADO肯定出錯,我相信肯定有不少的朋友經歷過這種問題的:

我的線程代碼如下:

unit Unitquerythread;

interface

uses
  windows,SysUtils,Classes, Dialogs,ADODB,db, NMMSG, ActiveX{必須要有};

type
  QueryThread = class(TThread)
  PRivate
   FComputerInfor,Fipaddressinfo: string;  //傳遞的信息
   FAdoQuery,FAdoQUserInfor:TadoQuery;  //動態生成的表一,表2
  
   Fadoconnection:Tadoconnection;  //動態生成的連接
   Fnmmsg,FNMretureMSG:TNMMSG;//用來發送返回信息的組件
filestream:tfilestream;
    procedure ExtractInfor(TransInfo:string{自定義的從該提交信息中分離信息的過程});
    procedure ShellexeQuery;
  Destructor Destroy;

  protected
    procedure Execute; override;
  public
constructor  create(ComputerInfor:string;{傳輸來的計算機信息}IPaddressinfo:string{傳輸來的IP地址信息};nmmsg,NMretureMSG:TNMMSG);
  end;
var
  ExtractDomainUser:string;  //提取出來的域用戶名
  ExtractComputername:string;//提取出來的計算機名稱
  ExtractDomainname:string;//提取出來的域名
  strlist:Tstringlist;
  IPlist:Tstringlist;//保存查找到的本工作組的ip地址信息
  const defeat='defeat';  //驗證失敗,必須注銷客戶機,在數據庫中重新進行寫入


implementation


  uses Unitsendthread;


constructor QueryThread.create(ComputerInfor, IPaddressinfo: string;nmmsg,NMretureMSG:TNMMSG);
begin
  CoInitialize( nil );//使用com對象必須要初始化
 
inherited create(false);
  FreeOnTerminate:=true;
  FComputerInfor:=ComputerInfor;
  FIPaddressinfo:=IPaddressinfo;
  IPlist:=Tstringlist.create;//創造ip列表
  FAdoQuery:=TAdoQuery.Create(nil);     //動態生成表一
  FAdoQUserInfor:=TadoQuery.Create(nil);//動態生成表2
  Fadoconnection:=Tadoconnection.Create(nil);//動態生成的連接
  Fadoconnection.LoginPrompt :=false;
  Fadoconnection.KeepConnection :=true;
  Fadoquery.Connection:=Fadoconnection;
  FAdoQUserInfor.Connection :=Fadoconnection;
  Fadoconnection.ConnectionString :='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=PersonInformation.mdb;Mode=Read;Persist Security Info=False';


  Fnmmsg:=nmmsg;
  FNMretureMSG:=NMretureMSG;
  strlist:=Tstringlist.Create;
 
end;

destructor QueryThread.Destroy;
begin
  FAdoQuery.FREE;
  FAdoQUserInfor.FREE;
  Fadoconnection.Free;
  strlist.Free;
  iplist.free;
  CoUnInitialize;//必須使用
inherited destroy;
end;

procedure QueryThread.Execute;
begin

try
 begin
  extractinfor(FComputerInfor);  //進行信息提取
 Synchronize(ShellexeQuery);//
 end;
except

self.Terminate;

end;

end;

procedure QueryThread.ExtractInfor(TransInfo: string);//改過程進行提取用#進行分割//的串里的各個字符串

integer;
j:array [1..2]of integer;//用來保存分割符的位置
H,L,M,N:integer;//進行組合字符串時的循環參數

begin
 
局變量,首先清空
      ExtractDomainUser:='';
      ExtractDomainname:='';
      ExtractComputername:='';
      H:=1;

//=================================
 try
    begin
         for i := 1 to length(TransInfo) do

        if TransInfo[i]='#' then //找到了
           begin
            j[H]:=i;
            
            inc(H);
            continue;  //跳出循環
           end;

    BEGIN
     for L:=1 to j[1]-1 do
          ExtractDomainUser:=ExtractDomainUser+TransInfo[L]; //提取的登陸域用戶名
          ://showmessage(extractdomainuser);
     for M:=j[1]+1 to j[2]-1 do
          ExtractDomainname:=ExtractDomainname+TransInfo[M];//提取的域控制器名
        //showmessage(extractdomainname);
     for N:=j[2]+1 to length(trim(TransInfo)) do
          ExtractComputername:=ExtractComputername+Transinfo[N];//提取的計算機名
         //showmessage(extractcomputername);
    END;
   end;//進行異常處理
  Except
   // messagebox(0,'信息提取出現錯誤!','提示信息',mb_iconinformation);
  end;
end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure QueryThread.ShellexeQuery;
var
    mark:string;   //保存查找到的工號信息
    SkillInfor:string;
    RetureInformation:string; //返回個客戶端的信息
    WorkGroupUserInfor:Tstringlist;
    filename:string;

begin
 try
   begin
      
       FAdoQuery.Close;
       Fadoquery.SQL.Clear;
       FAdoQuery.SQL.Add ('SELECT * From LOGON WHERE DomainUser='+'"'+ExtractDomainUser+'"'+'and DomainName='+'"'+ExtractDomainname+'"'+'and ComputerName='+'"'+ExtractComputername+'"'+'and IPaddress='+'"'+FIPaddressinfo+'"');
       FAdoQuery.Prepared :=true;
       FAdoQuery.active:=true;
file://=====================================================================
   if (FAdoQuery.fieldbyname('WorkMark').asstring ='') or (FAdoQuery.fieldbyname('Privilege').asstring='')  then //沒有查到工號信息
         begin

             Fnmmsg.Disconnect;
             Fnmmsg.Host:=FIPaddressinfo;
             Fnmmsg.Port :=6711;
             Fnmmsg.FromName :='a';
             Fnmmsg.PostIt(defeat); //沒有找到權限和工號則發送錯誤消息
             FAdoQuery.active:=false;
         end

  else      //查詢到了工號,和權限信息 ,從階連表中得到所有信息
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     begin

              strlist.Clear;
              strlist.Add(FAdoQuery.fieldbyname('WorkMark').asstring);//把工號寫入
              mark:=FAdoQuery.fieldbyname('WorkMark').asstring; //將工號寫入mark臨時變量

              FAdoQuery.close; //關閉第一個數據集
   //===========進入第二個表進行查找===============================================
    with FAdoQUserInfor do
       begin
            
              if active =true then close;   //關閉數據集
              sql.Clear;

              sql.Add('Select * From WORKER Where WorkMark='+'"'+mark+'"'); //該部分可能要求具體化內容
              Prepared :=true;
              open;
              //連接第二個線程時這里出現問題

            if (fieldbyname('Phone').asstring='')or (fieldbyname('Name').asstring='')or (fieldbyname('SkillLevel').asstring='')then
               begin
             showmessage('nil');
                  Fnmmsg.Disconnect;
                  Fnmmsg.Host:= FIPaddressinfo;
                  Fnmmsg.Port :=6711;
                  Fnmmsg.FromName :='b';
                  Fnmmsg.PostIt(defeat);  //發送錯誤消息
                  close;
               end

           else    //如果找到了電話號碼
               begin

                   strlist.add(fieldbyname('Name').asstring);  //寫入姓名
                   SkillInfor:=fieldbyname('SkillGroup').asstring;
                   strlist.add(fieldbyname('SkillGroup').asstring+'業務處理='+fieldbyname('SkillLevel').asstring); //上海市業務處理=1
                   strlist.Add(fieldbyname('Phone').asstring);  //寫入電話號碼
                 
                   RetureInformation :=strlist.Strings[0]{工號}+'#'+strlist.Strings[1]{姓名}+'#'+strlist.Strings[2]+'#'{技能信息}+strlist.strings[3]{電話號碼};
                   //edit;                      //煩會給客戶端的信息
                  // fieldbyname('IsLogon').asstring:='1'; //登錄成功,寫入成功標志
                  // Post;

                   FNMretureMSG.Disconnect;
                   FNMretureMSG.Host :=FIPaddressinfo;
                   FNMretureMSG.Port:=6722; //回傳信息遠程端口為6722;
                   FNMretureMSG.PostIt(RetureInformation);  //返回成功的信息


/·······························
   {進行查詢工作組信息,然后傳送信息}
                   if active =true then close;
                   sql.clear;
                   SQL.Add('SELECT * FROM WORKER WHERE SkillGroup='+'"'+SkillInfor+'"');
                   open;
                
                   WorkGroupUserInfor:=Tstringlist.create;

                 while not eof do
                  begin
                   WorkGroupUserInfor.Add(fieldByName('Name').asstring ); {index0 name}
                   WorkGroupUserInfor.Add(fieldByName('WorkMark').asstring ); {index1 workmark}
                   WorkGroupUserInfor.Add(fieldByName('Phone').asstring );    {index2 Phone}
                   WorkGroupUserInfor.Add(fieldByName('SkillGroup').asstring +'業務處理='+fieldbyname('SkillLevel').asstring);{index3 SkillGroup}
                   IPlist.Add(fieldbyname('IPaddress').asstring); ://所有的ip地址保留到內存中
                   //showmessage(fieldbyname('IPaddress').asstring);
                   iplist.SaveToFile (fieldByName('SkillGroup').asstring+'IPlst.INI');
                   next;
                 end;
                 WorkGroupUserInfor.SaveToFile(fieldByName('SkillGroup').asstring+'.ini');
                 close;
             end;
          end;
     end;
   end;
  except      //防止查詢失敗
    begin
      FAdoQuery.close;
      FAdoQUserInfor.close;
   end;
 end;

 end;

end.
注意:使用這兩個函數應該加上activex.pas單元,否則,無法運行。

我個人認為,如果開發基于ADO的多線程操作,最好在每個線程中放置一個連接,而數據集和數據連接都使用動態生成,當然你必須要注意必須要保證線程能過正常的釋放,否則你的電腦很快就快死機了,呵呵,當然還有第二種方法,你可以生成一個數據模塊,靜態放置數據集和ADOCONNECTION組件,然后使該數據模塊不在程序開始時生成,而可以在線程中動態的生成,這種方法也可以,有興趣的朋友可以試一下二者之間的執行效率。

而對于ADO,我認為在開始情況下,如果不初始函數和后來的釋放函數,卻不能報錯,應該是一個BUG吧。


上一篇:當單擊DBGrid中的標題欄時,進行排序

下一篇:類,接口與動態鏈接庫

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 日韩电影一区二区三区 | 九草av| 韩国一级免费视频 | 免费网站看v片在线a | 欧美精品一区二区久久 | 狠狠久久伊人中文字幕 | 久久久久久久久久性 | 国产精选电影免费在线观看网站 | 日韩视频一区二区三区四区 | 国产精品久久久久久久久久三级 | 福利在线免费视频 | 婷婷久久影院 | 毛片免费看电影 | 国产一区二区免费在线观看视频 | 成人在线免费观看小视频 | 久久爽久久爽久久av东京爽 | 成人在线不卡 | 91成人久久 | 久久欧美亚洲另类专区91大神 | 九九视屏| 一级一级一级一级毛片 | av电影在线观看网址 | 一级片久久免费 | 成人毛片免费 | 久久精品亚洲欧美日韩精品中文字幕 | 欧美日韩夜夜 | 一区国产在线 | 亚洲国产超高清a毛毛片 | 毛片一区二区三区 | 亚洲第一页综合 | 精品一区二区三区免费看 | 国产精品成人一区 | 日本a∨精品中文字幕在线 被啪羞羞视频在线观看 | 日本成人一区二区三区 | 美女又黄又www | 日韩中文字幕三区 | av在线免费看网站 | 一级片免费在线 | 国产污污视频 | 一区二区三区视频在线观看 | 一级毛片看|