線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:3721
推到 Plurk!
推到 Facebook!

出現"Lost connection to MySQL Server during query"錯誤

答題得分者是:smallfox
ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2010-10-13 10:12:52 IP:124.219.xxx.xxx 訂閱
各位前輩您們好  !!!

小弟目前在處理一支程式,把原本DB從Access 改成 MySQL。
連接資料庫的DELPHI元件為"TADOConnection" and " TADOQuery"
程式邏輯為
[code cpp]
ADOQuery1.Close;
ADOQuery1.SQL.Text:='XXXXXXXXXXXXXXXXXXXX';
ADOQuery1.Open;
for Loop
.............;
.............;
.............;
ADOQuery1.Append;
.........;
.........;
ADOQuery1.Post;
end Loop;
ADOQuery1.Close;
[/code]
如果For Loop 只跑一次的話,資料可以正確無誤的寫入MySQL資料庫(應該可以證明程式片段無誤),
但是,如果For Loop 跑兩次以上,就會出現"Lost connection to MySQL Server during query"錯誤(詳細錯誤訊息如附檔)。
小弟已經有先上網找過相關資料,可惜未能解決問題,在此求助於各位前輩幫忙了~Orz
請前輩們指點一下小弟,可能哪邊錯誤了!!!

系統 : WIN XP SP3
開發語言軟體 : Delphi 2010
MySQL版本 : mysql-5.0.77-win32(mysql-essential-5.1.39-win32也試過一樣)
MySQL ODBC : mysql-connector-odbc-3.51.27-win32(mysql-connector-odbc-5.1.6-win32 也試過一樣 )


PS:由於實際程式碼過長,只能大概表達,請見諒!!!。

老大仔
尊榮會員


發表:78
回覆:837
積分:1088
註冊:2006-07-06

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-10-13 11:10:48 IP:59.120.xxx.xxx 未訂閱
假如您的SQL指令是查尋的話,那麼...
1. for 迴圈之前要先指定到第一筆。
2. for 迴圈之中需判斷是否有該筆資料,沒有的話則新增,有的話則更新。


===================引 用 ac910127 文 章===================
各位前輩您們好 !!!

小弟目前在處理一支程式,把原本DB從Access 改成 MySQL。
連接資料庫的DELPHI元件為"TADOConnection" and " TADOQuery"
程式邏輯為
[code cpp]
ADOQuery1.Close;
ADOQuery1.SQL.Text:='XXXXXXXXXXXXXXXXXXXX';
ADOQuery1.Open;
for Loop
.............;
.............;
.............;
ADOQuery1.Append;
.........;
.........;
ADOQuery1.Post;
end Loop;
ADOQuery1.Close;
[/code]
如果For Loop 只跑一次的話,資料可以正確無誤的寫入MySQL資料庫(應該可以證明程式片段無誤),
但是,如果For Loop 跑兩次以上,就會出現"Lost connection to MySQL Server during query"錯誤(詳細錯誤訊息如附檔)。
小弟已經有先上網找過相關資料,可惜未能解決問題,在此求助於各位前輩幫忙了~Orz
請前輩們指點一下小弟,可能哪邊錯誤了!!!

系統 : WIN XP SP3
開發語言軟體 : Delphi 2010
MySQL版本 : mysql-5.0.77-win32(mysql-essential-5.1.39-win32也試過一樣)
MySQL ODBC : mysql-connector-odbc-3.51.27-win32(mysql-connector-odbc-5.1.6-win32 也試過一樣 )


PS:由於實際程式碼過長,只能大概表達,請見諒!!!。

ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#3 引用回覆 回覆 發表時間:2010-10-13 13:03:18 IP:124.219.xxx.xxx 訂閱
很感謝您的回答。
很抱歉,沒說清楚。!!!
這並不是查詢,而是做"Insert data"的動作。

不知前輩能否在指點一下可能的錯誤地方。

再次感謝您的回答 !!
老大仔
尊榮會員


發表:78
回覆:837
積分:1088
註冊:2006-07-06

發送簡訊給我
#4 引用回覆 回覆 發表時間:2010-10-13 14:03:13 IP:59.120.xxx.xxx 未訂閱
既然你的SQL指令是insert
那麼就直接使用迴圈去新增
for i := 0 to Memo1.Lines.Count - 1 do
begin
ADOQuery1.Close;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('------');
ADOQuery1.ExecSQL;
end;

===================引 用 ac910127 文 章===================
很感謝您的回答。
很抱歉,沒說清楚。!!!
這並不是查詢,而是做"Insert data"的動作。

不知前輩能否在指點一下可能的錯誤地方。

再次感謝您的回答 !!
ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#5 引用回覆 回覆 發表時間:2010-10-13 14:52:50 IP:124.219.xxx.xxx 訂閱
首先感謝您在次熱心的為我解答。

我為我的表達能力感到抱歉 !!!

請容許我再次描述狀況。

1 : 我所謂的"InSert data的動作" 是指 我利用了
ADOQuery1.Append;
ADOQuery1.FieldByName('XXXXXXX').AsString:='XXXXXXXXX';
.......
.......
.......
ADOQuery1.Post;
藉由這樣的語法完成"新增一筆資料到資料庫中"。
而非是我的SQL語法是"InSert "。

2:由於同樣的程式語法,使用Access資料庫不會出現問題,可是在將資料庫改成MySQL資料庫後,
便出現了此錯誤訊息。推測可能是Access資料庫 與 MySQL資料庫 有些許不同,才會在貴網站發文
請教各位前輩指導。

由於在Access資料庫不會出現問題,固小弟盼望能在不修改程式碼的狀況下,能找出問題的所在,並解決之。

在次感謝回答問題的前輩,也期待其他前輩不吝嗇指導
謝謝!!!
smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#6 引用回覆 回覆 發表時間:2010-10-14 01:27:02 IP:203.70.xxx.xxx 訂閱
你有追蹤發生 "Lost connection to MySQL Server during query" 訊息時, 是在哪一行程式嗎?

Append ? or Post ?

是否有在 AfterPost 事件中撰寫程式碼, 導致關閉了 TADOConnection.Connected ?

or

TADOQuery.Connection 被設成 NIL 了 ?

若 上述問題都不成立, 且 TADOConnection.Connected=True, 哪你可能要檢查一下 OBDC 的連線,
是否 MySQL 連線上有問題 ?
ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#7 引用回覆 回覆 發表時間:2010-10-14 16:17:27 IP:124.219.xxx.xxx 訂閱
感謝 smallfox 的回覆 !!!

1: 我追蹤過錯誤發生的點,在Post的那一行。
2: SQL的程式碼是在寫在Thread中,個人認為同一時間裡只有一個Thread在對資料庫作讀寫。
(測試階段只開一條Thread而已)並非在大大所
說的AfterPost 事件中撰寫程式碼。

3: ODBC連線應該是正常的,因為如果For 迴圈指跑一次的話,就不會有錯誤發生,跑兩次以上就會有
錯誤發生(原本的文章內有題到)。不過還是請教大大,可否提供您檢查ODBC連線的方式,好讓小弟確認一下,
因為以小弟認知的方式,ODBC連線是正常的。

在次感謝大大的回覆 !!!


PS:不知為何,最近上貴網站 or PO 文 總是出現連線逾時的現象,固若太慢回覆,請各位前輩見諒!!!
===================引 用 smallfox 文 章===================
你有追蹤發生 "Lost connection to MySQL Server during query" 訊息時, 是在哪一行程式嗎?

Append ? or Post ?

是否有在 AfterPost 事件中撰寫程式碼, 導致關閉了 TADOConnection.Connected ?

or

TADOQuery.Connection 被設成 NIL 了 ?

若 上述問題都不成立, 且 TADOConnection.Connected=True, 哪你可能要檢查一下 OBDC 的連線,
是否 MySQL 連線上有問題 ?
smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#8 引用回覆 回覆 發表時間:2010-10-14 23:29:27 IP:203.73.xxx.xxx 訂閱
建議你在 Post 之前加入幾行追蹤程式碼:

ADOQuery2.Close;
ADOQuery2.SQL.Text:='SELECT COUNT(*) FROM 某TABLE WHERE 1=0';
ADOQuery2.Open;

如果迴圈在跑第二次時, 若 ODBC 以斷線, 此時 TADOConnection.Connected 仍會為 True,
ADOQuery2.Open 就會出錯,
若 ADOQuery2.Open 可以順利執行, 那麼問題可能出在 ADOQuery1;
建議你還是在 ADOQuery2.Open 之前, 追蹤一下 TADOConnection.Connected 狀態
&

ADOQuery1.Connection 是否為 NIL
以便了解是否為 ODBC 斷線 or ADOQuery1 問題.

(說不定是 MySQL 在第一次寫入後, 就中斷連線)

請問 ADOQuery1.LockType = ?

ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#9 引用回覆 回覆 發表時間:2010-10-15 10:12:07 IP:124.219.xxx.xxx 訂閱
在次感謝大大的回覆 !!!

小弟根據大大的建議,進行了測試,結果
測試程式碼片段
[code cpp]
ADOQuery1.Append;
ADOQuery1.FieldByName('XXXX').AsString:='XXXXXXX';
......;
......;ADOQuery1.Connection 是否為 NIL
以便了解是否為 ODBC 斷線 or ADOQuery1 問題.

(說不定是 MySQL 在第一次寫入後, 就中斷連線)

請問 ADOQuery1.LockType = ?

編輯記錄
ac910127 重新編輯於 2010-10-15 10:15:06, 註解 無‧
ac910127 重新編輯於 2010-10-15 10:16:28, 註解 無‧
ac910127 重新編輯於 2010-10-15 10:18:37, 註解 無‧
ac910127 重新編輯於 2010-10-15 10:19:45, 註解 無‧
ac910127 重新編輯於 2010-10-15 10:34:17, 註解 無‧
ac910127 重新編輯於 2010-10-15 10:47:10, 註解 無‧
smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#10 引用回覆 回覆 發表時間:2010-10-16 16:22:20 IP:203.73.xxx.xxx 訂閱
測試程式碼改成:

ADOQuery1.FieldByName('xxx').AsString='xxxxxxxxxxxx';
....
....
if (not ADOQuery1.Connection.Connected) then ShowMessage('xxx');
ADOQuery2.Close;
ADOQuery2.SQL.Text:='xxxxxx';
ADOQuery2.Open;
//
ADOQuery1.Open;
....

看是中斷在 ADOQuery2 or ADOQuery1 ?

TADOQuery.LockType=ltOptimistic 表示在 Post 之後立即將異動的資料回寫後端資料庫.

ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#11 引用回覆 回覆 發表時間:2010-10-18 19:37:30 IP:124.219.xxx.xxx 訂閱
抱歉!!,這幾天多次想登入貴網站,或者登入後想回覆,均失敗。
真的很抱歉,現在才回覆您。

在次感謝您分享您的經驗 !!!

這次根據大大的提示進行測試,結果

1 : 並不會執行ShowMessage。

2 : 錯誤依舊發生在ADOQuery1.Open。

在次感謝大大的指導。
===================引 用 smallfox 文 章===================
測試程式碼改成:

ADOQuery1.FieldByName('xxx').AsString='xxxxxxxxxxxx';
....
....
if (not ADOQuery1.Connection.Connected) then ShowMessage('xxx');
ADOQuery2.Close;
ADOQuery2.SQL.Text:='xxxxxx';
ADOQuery2.Open;
//
ADOQuery1.Open;
....

看是中斷在 ADOQuery2 or ADOQuery1 ?

TADOQuery.LockType=ltOptimistic 表示在 Post 之後立即將異動的資料回寫後端資料庫.

smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#12 引用回覆 回覆 發表時間:2010-10-18 20:45:07 IP:218.161.xxx.xxx 訂閱
可以把 ADOQuery1 及 TADOConnection 所有的屬性及用到的事件名稱貼上來嗎?
ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#13 引用回覆 回覆 發表時間:2010-10-18 22:04:25 IP:124.219.xxx.xxx 訂閱
感謝大大在次的回覆 !!!
以下是屬性列表,由於是小弟自己打的,如單字有錯誤請見諒 !!
小弟是新手,固絕大部分都是預設值而以並沒進行修改。

ADOConnection1
CommandTimeOut := 15;
Connected := True;
ConnectionString := Provider=MSDASQL.1;
Password=1234;
Persist Security Info=False;
User ID=root;
Data Source=Local_MySql_20101006;
Initial Catalog=Defaultdb;
ConnectionTimeOut := 30;
ConnectOptions := coConnectUnspecified;
CursorLocation := clUseClient;
DefaultDatabase := Defaultdb;
IsolationLevel := ilCursorStability;
KeepConnection := True;
LoginPrompt := False;
Mode := cmUnknown;
Name := ADOConnection1;
Provider := MSDASQL.1;
Tag := 0;
事件 --> 沒有!!!

ADOQuery1
Active := True;
AutoCalcFields := True;
CacheSize := 1;
CommandTimeOut := 30;
Connection := ADOConnection1;
ConnectionString := '';
CursorLocation := clUseClient;
CursorType := ctStatic;
DataSource := '';
EnableBCD := True;
ExecuteOption := 預設值 沒改過,太多了不好打出來 抱歉
Filter := '';
Filtered := False;
LockType := ltOptimistic
MarshalOptions := moMarshalAll;
MaxRecords := 0;
Name := ADOQuery1;
ParamCheck := True;
Parameters := 預設 沒改過
Prepared := False;
SQL := Select * From MyTable;
Tag := 0
事件 --> 沒有!!!

感謝大大熱心的幫助,謝謝


===================引 用 smallfox 文 章===================
可以把 ADOQuery1 及 TADOConnection 所有的屬性及用到的事件名稱貼上來嗎?
smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#14 引用回覆 回覆 發表時間:2010-10-20 00:16:58 IP:203.67.xxx.xxx 訂閱
看樣子, 屬性上應該沒啥大問題, 建議調整一下下列屬性看看:

ADOConnection1.Mode:=cmShareDenyNone;

ADOQuery1.CacheSize:=1000; // 加大
ADOQuery1.EnableBCD:=False;
ADOQuery1.Prepared:=True;

如果跑第二次迴圈時還是 error 在 ADOQuery1.Post, 那改寫一些程式碼如下:

ADOQuery1.Close;
ADOQuery1.CacheSize:=1000;
ADOQuery1.LockType:=ltBatchOptimistic;
ADOQuery1.Prepared:=True;
ADOQuery1.SQL.Text:='xxxxxxxxxxx';
try
ADOQuery1.Open;
for loop do begin
ADOQuery1.Append;
ADOQuery1.FieldByName('xxx').AsString:='xxx';
.......
.......
ADOQuery1.Post;
end;
ADOQuery1.UpdateBatch;
ADOQuery1.Close;
except
ADOQuery1.Close;
ShowMessage('Update to DB Error !!');
end;

看看結果如何 .....
ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#15 引用回覆 回覆 發表時間:2010-10-20 10:34:09 IP:124.219.xxx.xxx 訂閱
實在非常感謝大大不厭其煩得指導小弟,小弟實在感謝 !!!

剛剛測試結果

1 : 第一種方式,依舊出現同樣的錯誤 !!! 追蹤下,得知依舊在迴圈的弟一次即發出錯誤訊息。
2 : 第二種方式,依舊出現同樣的錯誤 !!! 不過,小弟利用DEBUG模式進行追蹤,
發現,錯誤不在像之前" 第一次即發出錯誤訊息",而是" 在迴圈執行到最後一筆
資料的 POST 那一行發出錯誤訊息" !!!

以上 為利用大大測試之後的結果。

此次大大的建議,修改了一些屬性,小弟還是初學者,不知大大可否對
修改的屬性說明一下其用意 ?

在次感謝大大的幫助,對於佔用大大的時間,小弟深感抱歉 。
若大大手邊工作繁多,小弟可等待。
只希望能從此次的錯誤經驗,學習到MySQL資料庫的一些知識。

也歡迎其他大大一同加入討論指導,謝謝 。

===================引 用 smallfox 文 章===================
看樣子, 屬性上應該沒啥大問題, 建議調整一下下列屬性看看:

ADOConnection1.Mode:=cmShareDenyNone;

ADOQuery1.CacheSize:=1000; // 加大
ADOQuery1.EnableBCD:=False;
ADOQuery1.Prepared:=True;

如果跑第二次迴圈時還是 error 在 ADOQuery1.Post, 那改寫一些程式碼如下:

ADOQuery1.Close;
ADOQuery1.CacheSize:=1000;
ADOQuery1.LockType:=ltBatchOptimistic;
ADOQuery1.Prepared:=True;
ADOQuery1.SQL.Text:='xxxxxxxxxxx';
try
ADOQuery1.Open;
for loop do begin
ADOQuery1.Append;
ADOQuery1.FieldByName('xxx').AsString:='xxx';
.......
.......
ADOQuery1.Post;
end;
ADOQuery1.UpdateBatch;
ADOQuery1.Close;
except
ADOQuery1.Close;
ShowMessage('Update to DB Error !!');
end;

看看結果如何 .....
smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#16 引用回覆 回覆 發表時間:2010-10-21 02:00:22 IP:203.67.xxx.xxx 訂閱
經過這幾次的測試, 我認為問題應該在於
你將SQL的程式碼是在寫在Thread中之故.

提供給你的第二種方式, 如果是 ODBC等連線上有問題的話,
程式應該會中斷在 ADOQuery1.UpdateBatch, 而非迴圈的最後一次Post.

ADOQuery1.CacheSize:=1000;
ADOQuery1.LockType:=ltBatchOptimistic;

這兩行的目的都是設定資料欄位的處理要在 Client 端完成,
因此 Post 後的資料並不會回存到後端資料庫, 也就是仍在 Client 端的記憶體內.
待 ADOQuery1.UpdateBatch 時才一次性的將所有異動的資料回寫後端,
這樣的寫法可以避免存取資料時, 在Server端佔用過多的資源(如:記憶體, CPU, 硬碟存取...等).

我不知道你的 Thread 程序是如何撰寫及呼叫的, 若先不考慮這方面的問題的話,
再提供你下列方式:

// ADOQuery1 的屬性先恢復你之前的設定 ..
ADOQuery1.Close;
ADOQuery1.SQL.Text:='xxxxxx';
for Loop do begin
ADOQuery1.Open;
.....
ADOQuery1.Append;
ADOQuery1.FieldByName('xx').AsString='xxxx';
....
....
ADOQuery1.Post;
ADOQuery1.Close;
end;

你試看看吧 ....
ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#17 引用回覆 回覆 發表時間:2010-10-21 13:39:38 IP:124.219.xxx.xxx 訂閱
在次感謝您提供的建議與方式  !!

Thread的撰寫方式與呼叫,小弟均從貴網站找尋資料,
學習的。由於那部分程式碼較冗長,無法直接貼上網頁
,也因為不方便公布完整程式碼(小弟寫的實在不好!!),
故沒辦法檔案上傳,在此小弟深感抱歉。

大大這次提供的建議方法,經測試後依舊在第一筆資料
的POST便發出錯誤。

小弟可能要在重新研究Thread,找尋是否因Thread的關係
導致錯誤。

非常感謝大大一再的幫忙。
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#18 引用回覆 回覆 發表時間:2010-10-21 15:27:22 IP:203.75.xxx.xxx 未訂閱
既然是這樣
那就直接寫個測試程式,loop 10次,或是先改timer處理,如果不行,也方便處理問題

一開始就玩這麼大,出問題是很麻煩的

===================引 用 ac910127 文 章===================
在次感謝您提供的建議與方式 !!

Thread的撰寫方式與呼叫,小弟均從貴網站找尋資料,
學習的。由於那部分程式碼較冗長,無法直接貼上網頁
,也因為不方便公布完整程式碼(小弟寫的實在不好!!),
故沒辦法檔案上傳,在此小弟深感抱歉。

大大這次提供的建議方法,經測試後依舊在第一筆資料
的POST便發出錯誤。

小弟可能要在重新研究Thread,找尋是否因Thread的關係
導致錯誤。

非常感謝大大一再的幫忙。
ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#19 引用回覆 回覆 發表時間:2010-10-21 17:18:57 IP:124.219.xxx.xxx 訂閱
感謝大大的建議,小弟會多方嘗試看看。
謝謝



===================引 用 GrandRURU 文 章===================
既然是這樣
那就直接寫個測試程式,loop 10次,或是先改timer處理,如果不行,也方便處理問題

一開始就玩這麼大,出問題是很麻煩的


smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#20 引用回覆 回覆 發表時間:2010-10-24 00:35:38 IP:211.74.xxx.xxx 訂閱
你也可以用 ADOQuery1來讀取資料或做為是否新增的判斷,
而利用 ADOQuery2來新增記錄及回存後端 ...

(範例:)
ADOQuery1.SQL.Text:='SELECT * FROM TABLE1';
ADOQuery2.SQL.Text:='SELECT * FROM TABLE1 WHERE 1=0';
ADOQuery1.Open;
ADOQuery2.Open;
for loop do
if ADOQuery1.FieldByName('xx').AsString='' then begin
ADOQuery2.Append;
ADOQuery2.FieldByName('xx').AsString='xxxxx';
......
......
ADOQuery2.Post;
end;
ADOQuery1.Next;
end;
ADOQuery2.Close;
ADOQuery1.Close;

如果上述寫法還是發生錯誤在ADOQuery2.Post的話,
那就真的要考慮Thread的問題了

(不太明瞭為何要用Thread來處理資料新增?)

ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#21 引用回覆 回覆 發表時間:2010-10-25 10:32:24 IP:124.219.xxx.xxx 訂閱
感謝smallfox大大在次的回覆。
不過小弟在此有問題想請教 !!
[code cpp]
ADOQuery1.SQL.Text:='SELECT * FROM TABLE1';
ADOQuery2.SQL.Text:='SELECT * FROM TABLE1 WHERE 1=0';
ADOQuery1.Open;
ADOQuery2.Open;
for loop do
if ADOQuery1.FieldByName('xx').AsString='' then begin //當OPEN之後,ADOQuery1資料指標是指到最後一筆還是 空的??
ADOQuery2.Append;
ADOQuery2.FieldByName('xx').AsString='xxxxx';
......
......
ADOQuery2.Post;
end;
ADOQuery1.Next; //如果ADOQuery2成功POST之後,ADOQuery1裡面的資料會跟DB同步更新嗎??
end;
ADOQuery2.Close;
ADOQuery1.Close;

[/code]
未進行測試先提問,抱歉 !!!
以上的問題是以小弟目前對資料庫的概念有提出的問題,
若觀念上有錯誤,麻煩大大糾正指導了。

對於"為何要用Thread來處理資料新增"的問題,
在資料新增至資料庫前,還有一些必要的動作需處理,而這些
動作必須是"即時性"的,固小弟才會想到利用Thread的方式進行
處理。目前程式上的規劃是:
1 : Thread寫在一個 MyThread.pas檔
2 : ADO元件統一放在一個XXX DataModule中。
3 : 資料新增的程式碼是寫在MyThread.pas中。

如果大大覺得此種規劃不好,請多多建議,小弟會在參考衡。
畢竟要修改的話,變動量挺多的~"~!!!

在次感謝大大的回答。

===================引 用 smallfox 文 章===================
你也可以用 ADOQuery1來讀取資料或做為是否新增的判斷,
而利用 ADOQuery2來新增記錄及回存後端 ...

(範例:)
ADOQuery1.SQL.Text:='SELECT * FROM TABLE1';
ADOQuery2.SQL.Text:='SELECT * FROM TABLE1 WHERE 1=0';
ADOQuery1.Open;
ADOQuery2.Open;
for loop do
if ADOQuery1.FieldByName('xx').AsString='' then begin
ADOQuery2.Append;
ADOQuery2.FieldByName('xx').AsString='xxxxx';
......
......
ADOQuery2.Post;
end;
ADOQuery1.Next;
end;
ADOQuery2.Close;
ADOQuery1.Close;

如果上述寫法還是發生錯誤在ADOQuery2.Post的話,
那就真的要考慮Thread的問題了

(不太明瞭為何要用Thread來處理資料新增?)

smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#22 引用回覆 回覆 發表時間:2010-10-27 00:30:24 IP:203.67.xxx.xxx 訂閱
1.Open之後, 指標會停在第一筆.
2.Post之後, ADOQuery1內的資料並不會同步, 你必須Close 後再Open才會.
(如果你想同步, 直接使用 ADOQuery1 來新增記錄就好了)

原則上, 資料處理與回存有一定的時序(時程&順序),
除非你的 "必要的" 處理與新增記錄的動作之間無關聯性,
這時來做 Thread 那是 OK 的.

但如果你的 "必要的" 處理與新增記錄的動作之間有一定關聯
(也就是呼叫 Thread 之後接下來的程式碼與Thread內的處理有關),
就容易產生不確定性的問題, 如:

begin
call Thread; // do ADOQuery1.Append & Post;
ADOQuery1.SQL.Text:='xxxx';
ADOQuery1.ExecSQL; // 這一行可能就會與 Thread 內的動作衝突
end;

因為是平行處理, call Thread 後 Runtime 會繼續往下一個程式碼走,
此時想用 Thread 加快處理, 反而適得其反.




ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#23 引用回覆 回覆 發表時間:2010-10-27 10:41:57 IP:124.219.xxx.xxx 訂閱
感謝大大的回覆。
問題方面已了解。

程式上的規劃:
Main.pas
[code delphi]
begin
while 遇到需處理資料 do begin
Call MyThread;
end;
end
[/code]

MyThread.pas
[code delphi]
procedure MyThread.Execute;
begin
....... //解析此次資料可分成幾筆
....... // 進入 critical section
ADOQuery1.close;
ADOQuery1.SQL.Text:="XXXXXXXXXXXX";
ADOQuery1.Open;
for Loop
...... //將單一筆資料解析成DB Table 中各欄位所需要的值
...... //將單一筆資料解析成DB Table 中各欄位所需要的值
...... //將單一筆資料解析成DB Table 中各欄位所需要的值
ADOQuery1.Append;
........ //填欄位值
........ //填欄位值
ADOQery1.Post;
end;
ADOQuery1.close;
...... //退出 critical section

end
[/code]

以上大致上程式的佈局。
由於最近有其他工作需先處理,故未能及時進行部分邏輯修改及測試,
小弟在此深感抱歉。

在次感謝大大熱心的指導。
編輯記錄
ac910127 重新編輯於 2010-10-27 01:56:17, 註解 無‧
smallfox
高階會員


發表:2
回覆:113
積分:128
註冊:2003-02-19

發送簡訊給我
#24 引用回覆 回覆 發表時間:2010-10-27 17:23:48 IP:218.161.xxx.xxx 訂閱
依照你的架構, ADOQuery1 應改成動態比較不會有問題, 如:

var ADO: TADOQuery; HH, MM, SS, MS: Word;
begin
DecodeTime(Time, HH, MM, SS, MS);
try
ADO:=TADOQuery.Create(nil);
ADO.Name:=IntToStr(HH) IntToStr(MM) IntToStr(SS) IntToStr(MS); // 動態產生名稱 ..
ADO.Connection:=db1;
ADO.SQL.Text:='xxxxxx';
ADO.Open;
for loop do begin
......
......
ADO.Append;
......
......
ADO.Post;
end;
finally
ADO.Close;
ADO.Free;
ADO:=nil;
end;

ac910127
一般會員


發表:7
回覆:27
積分:11
註冊:2009-11-06

發送簡訊給我
#25 引用回覆 回覆 發表時間:2010-10-28 09:40:00 IP:124.219.xxx.xxx 訂閱
感謝smallfox大大再次提供建議,
小弟會找時間再嘗試看看,
感謝您 !!
系統時間:2024-05-07 13:37:40
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!