使用ADO,多執行緒訪問ACCESS資料庫的開發。 (轉)
本人最近正在進行呼叫中心的座席端和開發,座席端登入部分是進行提取主機資訊,然後使用SOCKET提交給伺服器,伺服器再在後臺中進行查詢資訊,進行對比,看是否允許座席端主機登入,因為我的中無法SERVER,所以 ,後臺資料庫暫時使用access小型資料庫進行代替,到後期可以改為SQLSERVER資料庫,,我在後臺資料庫中使用了兩個表,使用WORKMARK欄位將其相關聯,如果在第一個表中查詢到資訊以後馬上會進入第二個表中進行查詢,如果第一個表中的資訊符合,就返回個客戶第二個表中的資訊,因為座席端主機有200多臺,為了防止幾臺主機同時進行驗證資訊,引起衝突,我在伺服器端建立多執行緒,利用執行緒進行後臺的查詢,以及查詢結果的回傳,編寫成功後進行測試,發現當一個主機連線後可以測試成功,但是,當第二個或者以後的執行緒產生時,資料集在第一個表中可以查到正確的資訊,但是進入第二個表中時,會發現按照正確的查詢條件進行查詢時,查到的資訊都為NIL,而且經過跟蹤,發現,其實ADO已經找到了正確的資訊,而且已經傳送成功了,但是卻無法接收到,當時我在論壇中發表了一個帖子尋求幫助,原貼內容:/Expert/topic/1420/1420051.?temp=.3060114">
有些朋友說可能ACCESS資料庫不提供多執行緒訪問,但是我聽說很多的論壇中好像都使用了ACCESS進行後臺執行緒的查詢的。翻看MSDN中關於COM的說明:發現我的執行緒中竟然缺少最重要的兩個過程
CoInitialize( nil );凡是訪問com都應該使用。執行緒的關閉時應該使用CoUnInitialize;否則ADO肯定出錯,我相信肯定有不少的朋友經歷過這種問題的:
我的執行緒程式碼如下:
unit Unitquerythread;
interface
uses
,SysUtils,Classes, Dialogs,ADO,db, NMMSG, {必須要有};
type
QueryThread = class(TThread)
private
FComputerInfor,FIPaddressinfo: string; 遞的資訊
FAdoQuery,FAdoQUserInfor:TadoQuery; 態生成的表一,表2
Fadoconnection:Tadoconnection; 態生成的連線
Fnmmsg,FNMretureMSG:TNMMSG;//用來傳送返回資訊的
filestream:tfilestream;
procedure ExtractInfor(TransInfo:string{自定義的從該提交資訊中分離資訊的過程});
procedure exeQuery;
Destructor Destroy;
protected
procedure Execute; overr;
public
constructor create(ComputerInfor:string;{傳輸來的資訊}IPaddressinfo:string{傳輸來的資訊};nmmsg,NMretureMSG:TNMMSG);
end;
var
ExtractainUser: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);
FreeOnTenate:=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=.Jet.OLEDB.4.0;Data =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]; 取的登陸域使用者名稱
(extractdomainuser);
for M:=j[1]+1 to j[2]-1 do
ExtractDomainname:=ExtractDomainname+TransInfo[M];//提取的域控制器名
(extractdomainname);
for N:=j[2]+1 to length(trim(TransInfo)) do
ExtractComputername:=ExtractComputername+Transinfo[N];//提取的計算機名
(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 (' * From LOGON WHERE DomainUser='+'"'+ExtractDomainUser+'"'+'and DomainName='+'"'+ExtractDomainname+'"'+'and ComputerName='+'"'+ExtractComputername+'"'+'and IPaddress='+'"'+FIPaddressinfo+'"');
FAdoQuery.Prepared :=true;
FAdoQuery.active:=true;
if (FAdoQuery.fieldbyname('WorkMark').asstring ='') or (FAdoQuery.fieldbyname('Privilege').asstring='') then 有查到工號資訊
begin
Fnmmsg.Dinnect;
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]{電話號碼};
; 會給客戶端的資訊
// 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地址保留到中
(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,我認為在開始情況下,如果不初始函式和後來的釋放函式,卻不能報錯,應該是一個吧。
謝謝關注:
qq:53997882歡迎大家互相交流
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993106/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java多執行緒/併發12、多執行緒訪問static變數Java執行緒變數
- 多執行緒程式中對資料庫連線使用的疑問執行緒資料庫
- Android中Sqlite資料庫多執行緒併發問題AndroidSQLite資料庫執行緒
- 封裝ADO訪問資料庫的兩個類 (轉)封裝資料庫
- python使用多執行緒備份資料庫Python執行緒資料庫
- 求助!關於多執行緒連線資料庫的問題執行緒資料庫
- Oracle,SqlServer,Access資料庫通用訪問類設計(轉)OracleSQLServer資料庫
- 多執行緒同步的開發執行緒
- 使用委託開啟多執行緒(多執行緒深入)執行緒
- 直接通過ADO操作Access資料庫資料庫
- 多執行緒程式設計,處理多執行緒的併發問題(執行緒池)執行緒程式設計
- [轉]Matz, Koichi訪談(三):多執行緒執行緒
- springboot配置執行緒池使用多執行緒插入資料Spring Boot執行緒
- 資料訪問連線池和執行緒池執行緒
- 關於多執行緒訪問靜態方法的問題執行緒
- 同步寫兩個資料庫--多執行緒資料庫執行緒
- C#多執行緒開發-執行緒同步 02C#執行緒
- C#多執行緒開發-執行緒池03C#執行緒
- iOS 開發中的多執行緒iOS執行緒
- 利用ADO壓縮Access資料庫程式碼資料庫
- seam中使用多執行緒的問題執行緒
- Java多執行緒-執行緒池的使用Java執行緒
- Shell多執行緒備份資料庫的指令碼執行緒資料庫指令碼
- 【iOS開發】多執行緒 - 概述iOS執行緒
- iOS多執行緒全套:執行緒生命週期,多執行緒的四種解決方案,執行緒安全問題,GCD的使用,NSOperation的使用iOS執行緒GC
- C#多執行緒開發-任務並行庫04C#執行緒並行
- C#多執行緒開發-執行緒基礎 01C#執行緒
- 11. shell多執行緒備份資料庫執行緒資料庫
- 【java 多執行緒】多執行緒併發同步問題及解決方法Java執行緒
- 使用PowerBuilder同時訪問多個資料庫UI資料庫
- java多執行緒之執行緒的基本使用Java執行緒
- 多執行緒-執行緒組的概述和使用執行緒
- 多執行緒-執行緒池的概述和使用執行緒
- 多執行緒使用執行緒
- 多執行緒訪問—限制某個方法只執行一次執行緒
- JAVA多執行緒共享資料Java執行緒
- 多執行緒資料採集執行緒
- 多執行緒問題執行緒