全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:16231
推到 Plurk!
推到 Facebook!
[<<] [1] [2] [>>]

請教關於 multi thread 的問題

尚未結案
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-12-29 22:53:42 IP:210.192.xxx.xxx 未訂閱
請各位有經驗的前輩大大們幫小弟想一下,實在是快丟了工作了,拜託拜託~~~~~ 小弟在本站看了不少文章,有關於thread 的,有看到說「如果要三個Thread同時執行, 就不能用Synchronize().」的例子,這乃是因為「Synchronize()會把要做的事交給Main Thread來做」,這個我董,可是小弟目前的情況可能比這個還來得複雜一些,請有經驗的大大幫個忙~~~~ 小弟的程式是一支授權程式,就像網路遊戲的伺服器一樣,當玩家上線時我的程式必需到資料庫查這位玩家的剩餘使用時間,然後給予授權,問題就在於當同一時間有很多位玩家上線時,我真的不知如何處理了,我只有一個thread,問題有三: 1: 如果我的thread 不使用Synchronize()來代入main thread 做,可能不行,因為thread 內部有透過bde 元件去讀取資料庫的資料。 2:如果我的thread 使用Synchronize()這樣做可能不是multi thread 因為他可能一個個排完隊後一個個去做。 3:到現在我快被一些書給搞混了,如果我只有一個thread 的程式,但是當有使用者來敲門時我就必需做一次 thread = new TThread 的動作,也就是說如果有十位user 來,我就會配置出十個同樣動作的 thread 出來,但我搞不清的是這十個thread 是屬於同歩呢?或者是一個個等 main thread 做完後才做下一個thread 呢?如果是一個個等,那我的user 一次如果有一百位同時敲門時,這恐怕有得等了,如果是十個thread 同歩,我該怎麼處理才會安全呢?因為目前我的程式沒有做Synchronize()當有大量user 上線敲門時,程式就會出現 EAccessViolation 的錯誤訊息。 請問我該怎麼做才能達到安全,又可以multi thread 同時執行呢?? 不知小弟以上的描述是否清楚呢?需要小弟把處理 thread 的那部份程式 po 上來嗎?真的拜託大家的幫忙拜託拜託~~~~~~~~~~
pwipwi
版主


發表:68
回覆:629
積分:349
註冊:2004-04-08

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-12-30 02:11:03 IP:211.76.xxx.xxx 未訂閱
smartboss你好:     我提供一些自已的想法讓你參考看看....        如果你是用Indy的TCP元件的話,可能更簡單就可以處理:Indy的TCP/IP Server會對每一個Connection自動產生一個Thread。(換句話說,可以不用自已new一個thread來處理一個Connection)當這個Thread產生後,你可以在Thread裡動態產生bde的元件。這時產生的bde只屬於一個單一Thread,因此仔細處理不會有rentry的的問題(當然也不用Synchronize)。bde得到資料後,就可以送封包回Client端,然後就完成了。        可以確定的是,資料庫是可以handle multithread的。而且bde如果不會用到視窗類的元件,或許也不必用到Synchronize來呼叫。        不知道能否幫上忙...(只希望別愈幫愈忙...< >) 如果觀念有誤,也煩請版上大大們指正囉~< >
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-12-30 09:52:56 IP:211.76.xxx.xxx 未訂閱
pwipwi 兄您好: 感謝您提供給小弟的看法,而小弟的做法其實有一部份極像您所提供的做法 但是我想問題恐怕不是出在元件上,而可能是我在 thread 呼叫前的處理上 出了什麼問題所導致,我把程式處理及呼叫thread的動作部份 po 上來,請 pwipwi看能否多少再給小弟一點意見。 我使用的是udp元件在這支程式裡,在main.cpp的部份,我將開thread的動作 做在觸發回應的func裡, main.cpp ... ... ... ... void __fastcall TfrmRadius::ReceData(char *rece,AnsiString FIP, int Port) { if (rece_data[0]!='\0') Tthread = new thread(true,rece,FIP,Port); //由此進入 thread } 而我的 thread 的部份的動作如下: thread.cpp ... ... ... __fastcall thread::thread(bool CreateSuspended, char *tBuffer,AnsiString FIP, int Port) : TThread(CreateSuspended) { memset(szBuffer, 0, sizeof(szBuffer)); memcpy(szBuffer, tBuffer, 1024); from_ip=FIP; from_port=Port; Resume(); <-----在這裡喚醒 execute() 請問 pwipwi及其他前輩們不知這樣是否合法??? } void __fastcall thread::Execute() <----在來在 execute 裡之所以有setname 是書上教的,以及 { Synchronize 也是書上教的,只是我的問題一直搞不董的 SetName(frmRadius->thread_var); 是在Synchronize到底是防止資源非法共用的衝突,或者它 FreeOnTerminate=true; 只是純粹使thread的動作變成一個個排隊動作?? Synchronize(ReadPacket); } void thread::SetName(int var) <------setname如下,它的用意似乎是給每一個thread有一個名稱和id然而這用 { 意又為何,我還是不董?? AnsiString str = "Tthread"; THREADNAME_INFO info; info.dwType = 0x1000; info.szName = str.c_str(); info.dwThreadID = -1; info.dwFlags = 0; __try { RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD),(DWORD*)&info ); } __except (EXCEPTION_CONTINUE_EXECUTION) { } } void __fastcall thread::ReadPacket() <---------這裡面的動作就是bde去查資料庫的動作 { 小弟這部份做的就跟pwipwi 兄說的很相 .... 似是用動態產生bde的元件的方式在處理?? .... .... 因此小弟主要的問題是想問,在弟配置thread 的事前動做時是否有疏失,如Resume();放置的 位地方是否正確,以及為何如果小弟沒有做Synchronize(ReadPacket);的動作時,總是不用多 久就會出現EAccessViolation 的錯誤訊息,我在想可能是我thread的安排部份出現了差錯, 不知各位大大是否還有其它的看法的呢?多少提供給小弟一些意見,pwipwi 兄謝謝您的看法 致於看了小弟的程式後,您是否能再提供小弟一些意見來參呢???
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-12-30 12:06:20 IP:221.169.xxx.xxx 未訂閱
引言: Synchronize 也是書上教的,只是我的問題一直搞不董的是在Synchronize到底是防止資源非法共用的衝突,或者它只是純粹使thread的動作變成一個個排隊動作??
恩~~這個問題的答案,應該是當你在TThread呼叫Synchronize,THREAD會停下然肉把控制權丟還給MAIN THREAD,然後在MAIN THREAD之中做一下事情(就是你寫的ReadPacket FUNCTION) 看了一下你的程式,好奇的問一下SetName是用來幹嘛的?它的用意似乎是給每一個thread有一個名稱和id,除非你會在其他的地方使用到該THREAD,不然這段程式似乎不太需要.. 建議你去找本MULTI THREAD的書來看一下,偶這邊推薦一本 書名:Win32 多緒程式設計 (Multithreading Applications in Win32) 作者:Jim Beveridge % Robert Wiener著 / 侯俊傑 譯 出版商:碁峰資訊 這本書寫的還算蠻清楚的,可以看看,或許對你會有幫助 P.S 這本書偶是在台北市重慶南路的天瓏書局買的 ========================= 大家一起快樂寫程式
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-12-30 12:18:30 IP:221.169.xxx.xxx 未訂閱
引言: 1: 如果我的thread 不使用Synchronize()來代入main thread 做,可能不行,因為thread 內部有透過bde 元件去讀取資料庫的資料。 2:如果我的thread 使用Synchronize()這樣做可能不是multi thread 因為他可能一個個排完隊後一個個去做。 3:到現在我快被一些書給搞混了,如果我只有一個thread 的程式,但是當有使用者來敲門時我就必需做一次 thread = new TThread 的動作,也就是說如果有十位user 來,我就會配置出十個同樣動作的 thread 出來,但我搞不清的是這十個thread 是屬於同歩呢?或者是一個個等 main thread 做完後才做下一個thread 呢?如果是一個個等,那我的user 一次如果有一百位同時敲門時,這恐怕有得等了,如果是十個thread 同歩,我該怎麼處理才會安全呢?因為目前我的程式沒有做Synchronize()當有大量user 上線敲門時,程式就會出現 EAccessViolation 的錯誤訊息。 請問我該怎麼做才能達到安全,又可以multi thread 同時執行呢?? 不知小弟以上的描述是否清楚呢?
1: 如果你的thread 有透過bde 元件去讀取資料庫的資料,偶個人還是建議你乖乖的用Synchroniz吧,這樣比較安全,這是偶個人的經驗 2: YES 如果thread 使用Synchronize()這樣是一個個排完隊後一個個去做。 3: A. 若你程式一次產生10個THREAD,且不使用Synchronize(),那當然是同一個時間有10個THREAD『一起』在做事 B. 若你程式一次產生10個THREAD,且使用Synchronize(),那當然是同一個時間有10個THREAD『一起』在做事,但是當THREAD執行到Synchronize()則是排隊嘍 如果你要兼顧效能及安全,偶給你各建議,鼻要使用BDE改用M$的ADO,ADO可以在Multi Thread中運作,且不用Synchronize,當然你不可以在每一個THREAD都使用同一個ADO物件 ========================= 大家一起快樂寫程式
dllee
站務副站長


發表:319
回覆:2516
積分:1710
註冊:2002-04-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-12-30 13:08:44 IP:220.139.xxx.xxx 未訂閱
我不確定 BDE 在 Thread 內自己去 new 就一定可以 thread safe... 但以您的測試,如果在 Synchronize 時,是 OK 不會 Exception, 但在取消 Synchronize 就會 Exception 那基本上,您的 thread 啟動 程序是 OK 的,但在 Thread 內作的事是有問題的,特別是在 Synchronize 取消所作的事。 其實 Synchronize 也只是慢一點而已,畢竟 CPU 只有一個, 用 Synchronize 是會強迫一個一個作,不用 Synchronize 是同時作 (也是由系統決定, 每一個執行緒何時作, 作得快慢都不是我們能控制的) 如果您在 Synchronize 內不會作超過 2 秒,那 10 個人同時來也是最多等 20 秒。 真的要快就要像 pwipwi/lu 說的,不要用 Synchronize 但是您必需確保 在 Thread 內沒有操作到任何非 Thread safe 的 VCL 元件。 以我個人來說,穩定是第一,速度是第二,所以,一律使用 Synchronize 省得自找麻煩  < href="http://free.greenworld.com.tw/~dllee/" target="blank">吃軟也吃硬 dllee.ktop.com.tw StatPlus 系統資源監測器 @ KTOP VMASK - ViewMove Automation Software Kernel
------
http://blog.yam.com/dllee/
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-12-30 13:37:18 IP:211.76.xxx.xxx 未訂閱
引言: [quote] 1: 如果你的thread 有透過bde 元件去讀取資料庫的資料,偶個人還是建議你乖乖的用Synchroniz吧,這樣比較安全,這是偶個人的經驗 2: YES 如果thread 使用Synchronize()這樣是一個個排完隊後一個個去做。 3: A. 若你程式一次產生10個THREAD,且不使用Synchronize(),那當然是同一個時間有10個THREAD『一起』在做事 B. 若你程式一次產生10個THREAD,且使用Synchronize(),那當然是同一個時間有10個THREAD『一起』在做事,但是當THREAD執行到Synchronize()則是排隊嘍 如果你要兼顧效能及安全,偶給你各建議,鼻要使用BDE改用M$的ADO,ADO可以在Multi Thread中運作,且不用Synchronize,當然你不可以在每一個THREAD都使用同一個ADO物件 ========================= 大家一起快樂寫程式
LU 兄,謝謝您,提供給小弟這麼多寶貴的看法,現在我己經很清楚整個架構關係,但是仍然有幾個小問題再向您請教及站上前輩請教: 1:setname 是書上教的,沒錯是給thead 一個名稱和id ,但我不知其所以然為何??比方用在哪方面的應用時?? 2:要用ado 這是小弟一開使的想法後來被主導才改變的,但是我想我還是會把它改過來吧,而lu兄您提到的不能每個thread都使用同一個ado,言下之意似乎跟pwi兄所說的同意思,就是當thread被喚起後,在thread裡以動態的方式開啟一個ado的工作是嗎?? 3:一樣是在書上看到的,在程式中有一行FreeOnTerminate=true; 這樣的動作,小的實在不董它是做什,真正的功能為何?因為我有加沒加這行似乎一樣都能跑也沒有錯誤出現,這行真意為何呢?? 最後謝謝您並且同時提供相關書籍介紹感謝您!
pwipwi
版主


發表:68
回覆:629
積分:349
註冊:2004-04-08

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-12-30 13:42:24 IP:211.76.xxx.xxx 未訂閱
smartboss你好: 大概看了一下你的程式碼,我只能就我所看到的給一些建議… 1.Resume方向,如果你建立一個Thread後要讓他馬上開始跑,只要把CreateSuspended設為False。 2.你的FreeOnTerminate設為True,要小心不要delete Thread。 3.我也看不懂SetName的用意,或許可以試試不要用他...而且函式中 自已產生Exception。如果你的程式碼post正確的話,我覺得倒看起來很 "奇怪"...。 另外EAccessViolation的發生位置和讀寫的位置的值是多少?這些都有一定的意義可以協助判斷。
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-12-30 13:46:51 IP:211.76.xxx.xxx 未訂閱
引言: 我不確定 BDE 在 Thread 內自己去 new 就一定可以 thread safe... 但以您的測試,如果在 Synchronize 時,是 OK 不會 Exception, 但在取消 Synchronize 就會 Exception 那基本上,您的 thread 啟動 程序是 OK 的,但在 Thread 內作的事是有問題的,特別是在 Synchronize 取消所作的事。 其實 Synchronize 也只是慢一點而已,畢竟 CPU 只有一個, 用 Synchronize 是會強迫一個一個作,不用 Synchronize 是同時作 (也是由系統決定, 每一個執行緒何時作, 作得快慢都不是我們能控制的) 如果您在 Synchronize 內不會作超過 2 秒,那 10 個人同時來也是最多等 20 秒。 真的要快就要像 pwipwi/lu 說的,不要用 Synchronize 但是您必需確保 在 Thread 內沒有操作到任何非 Thread safe 的 VCL 元件。 以我個人來說,穩定是第一,速度是第二,所以,一律使用 Synchronize 省得自找麻煩 < face="Verdana, Arial, Helvetica"> 您的說法小弟董了,只不過如果要讓thread一個個排隊工作的話那小弟會覺得不如用timer的中斷方式是否來的容易,且可能也不會有Exception的問題出現,因為timer它也是一次次中斷來做的,不知小弟這樣說對嗎?? 我也越來越偏向您的主張了,「穩定是第一,速度是第二」呵呵~~~,謝謝您提供看法給小弟,如果大大您還有更新的想法歡迎提供給小弟學習的機會,謝謝您!
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#10 引用回覆 回覆 發表時間:2004-12-30 14:10:26 IP:211.76.xxx.xxx 未訂閱
引言: smartboss你好: 大概看了一下你的程式碼,我只能就我所看到的給一些建議… 1.Resume方向,如果你建立一個Thread後要讓他馬上開始跑,只要把CreateSuspended設為False。 2.你的FreeOnTerminate設為True,要小心不要delete Thread。 3.我也看不懂SetName的用意,或許可以試試不要用他...而且函式中 自已產生Exception。如果你的程式碼post正確的話,我覺得倒看起來很 "奇怪"...。 另外EAccessViolation的發生位置和讀寫的位置的值是多少?這些都有一定的意義可以協助判斷。
pwipwi 兄您好: 1:您的意思是Resume不用了,直接換成CreateSuspended=False; 的意思嗎? 2:小弟剛才才在問lu兄,說FreeOnTerminate設為True 這是什麼意思,我還不太董,但是小弟早上有改了一部份的程式,發現當 FreeOnTerminate設為True 動作時它會去跑這個部份的程式 __fastcall thread::~thread() { frmRadius->thread_var--; frmRadius->Tthread->Terminate(); <----而pwi兄您所說的不要把它delect 掉了是指這一行嗎??或者指的是 delete Tthread; 的動作呢?? } 3:SETNAME 好像站上的大大都沒有人看過,呵呵~~這部份小弟是在書上看到的,確定沒有po錯,小弟在程式裡也有加這行,但是小弟到書局裡把將近二十本的c builder的書都搬下來看了,有關thread部份的書都沒有提到這部份,所以,不只pwi兄您覺得怪,連小弟在抄時都覺得怪,只是當時小弟真是搞到沒有任何新意可以改變程式的錯誤了,所以才將他加上去的。 4:EAccessViolation的發生位置和讀寫的位置的值是多少,小弟今天早上把這部份的bug 抓到了, 是我有一個指標 char *strbuff; AnsiString str; strbuff = str.c_str; <-----指向了一個 ansistring 字串 free(strbuff); <----- 結果我誤以為它是配置的記憶區段,要把它清掉時所造成! 致於如果小的把Synchronize()拿掉後程式一樣會再出現EAccessViolation,只是每次位址都不同,小弟查一下再向您請教一翻。 謝謝您,提供這麼多意見和看法,歡迎再給小弟教導,thx!
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#11 引用回覆 回覆 發表時間:2004-12-30 14:26:09 IP:221.169.xxx.xxx 未訂閱
引言: 1:setname 是書上教的,沒錯是給thead 一個名稱和id ,但我不知其所以然為何??比方用在哪方面的應用時?? 2:要用ado 這是小弟一開使的想法後來被主導才改變的,但是我想我還是會把它改過來吧,而lu兄您提到的不能每個thread都使用同一個ado,言下之意似乎跟pwi兄所說的同意思,就是當thread被喚起後,在thread裡以動態的方式開啟一個ado的工作是嗎?? 3:一樣是在書上看到的,在程式中有一行FreeOnTerminate=true; 這樣的動作,小的實在不董它是做什,真正的功能為何?因為我有加沒加這行似乎一樣都能跑也沒有錯誤出現,這行真意為何呢??
1. 一般來說是這樣,偶寫一個新的程式(跟你的程式無關,鼻要搞混了),有 > 當然偶不是用類似> > >大家一起快樂寫程式
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#12 引用回覆 回覆 發表時間:2004-12-30 15:29:18 IP:211.76.xxx.xxx 未訂閱
引言: 3.FreeOnTerminate=true; 是指這個THREAD結束後會自己把所佔的資源釋放掉(相當於DELETE的效果),簡單說,就是你不需要在DELETE該THREAD,只需要NEW就好了
lu 兄,那請問,如果程式改成如下: __fastcall thread::thread(bool CreateSuspended, char *tBuffer,AnsiString FIP, int Port) : TThread(CreateSuspended) { memset(szBuffer, 0, sizeof(szBuffer)); memcpy(szBuffer, tBuffer, 1024); from_ip=FIP; from_port=Port; FreeOnTerminate=true; <--- 我把它加在 resume 之前讓它自己跑完後,自己去清,把它放在這裡是否可以呢?正確嗎?? Resume(); } void __fastcall thread::Execute() { SetName(frmRadius->thread_var); Synchronize(ReadPacket); }
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#13 引用回覆 回覆 發表時間:2004-12-30 16:47:07 IP:221.169.xxx.xxx 未訂閱
引言:
__fastcall thread::thread(bool CreateSuspended, char *tBuffer,AnsiString FIP, int Port)
: TThread(CreateSuspended)
{
memset(szBuffer, 0, sizeof(szBuffer));
memcpy(szBuffer, tBuffer, 1024);
from_ip=FIP;
from_port=Port;
FreeOnTerminate=true; <--- 我把它加在 resume 之前讓它自己跑完後,自己去清,把它放在這裡是否可以呢?正確嗎?? 
Resume(); 
} 
void __fastcall thread::Execute() 
{ 
SetName(frmRadius->thread_var); 
Synchronize(ReadPacket);    }
YES 把FreeOnTerminate=true;放在RESUME的前面就OK了 另外,看了一下你的程式,你的THREAD應該是一起動就要執行了,那你可以這樣做
__fastcall thread::thread(char *tBuffer,AnsiString FIP, int Port)
: TThread(false)  //直接將CreateSuspended設為FALSE
{
memset(szBuffer, 0, sizeof(szBuffer));
memcpy(szBuffer, tBuffer, 1024);
from_ip=FIP;
from_port=Port;
FreeOnTerminate=true;
} 
若你不想修改 thread 的建構程式那你可以在產生THREAD直接將CreateSuspended設為FALSE,如下例 Tthread = new thread(false,rece,FIP,Port); 一般來說,若你的THREAD一產生後就要啟動,大部分的人都是用上面兩種方法(至少在K.Top裡面的各位大大,大多是這樣寫低),而不是呼叫 > ========================= <>大家一起快樂寫程式
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#14 引用回覆 回覆 發表時間:2004-12-30 17:20:15 IP:211.76.xxx.xxx 未訂閱
引言:
引言:
__fastcall thread::thread(bool CreateSuspended, char *tBuffer,AnsiString FIP, int Port)
: TThread(CreateSuspended)
{
memset(szBuffer, 0, sizeof(szBuffer));
memcpy(szBuffer, tBuffer, 1024);
from_ip=FIP;
from_port=Port;
FreeOnTerminate=true; <--- 我把它加在 resume 之前讓它自己跑完後,自己去清,把它放在這裡是否可以呢?正確嗎?? 
Resume(); 
} 
void __fastcall thread::Execute() 
{ 
SetName(frmRadius->thread_var); 
Synchronize(ReadPacket);    }
YES 把FreeOnTerminate=true;放在RESUME的前面就OK了 另外,看了一下你的程式,你的THREAD應該是一起動就要執行了,那你可以這樣做
__fastcall thread::thread(char *tBuffer,AnsiString FIP, int Port)
: TThread(false)  //直接將CreateSuspended設為FALSE
{
memset(szBuffer, 0, sizeof(szBuffer));
memcpy(szBuffer, tBuffer, 1024);
from_ip=FIP;
from_port=Port;
FreeOnTerminate=true;
} 
若你不想修改 thread 的建構程式那你可以在產生THREAD直接將CreateSuspended設為FALSE,如下例 Tthread = new thread(false,rece,FIP,Port); 一般來說,若你的THREAD一產生後就要啟動,大部分的人都是用上面兩種方法(至少在K.Top裡面的各位大大,大多是這樣寫低),而不是呼叫 > < face="Verdana, Arial, Helvetica"> lu 兄,您的意思這樣小弟董了,pwipwi 兄,同時也謝謝您,您也同時提到這個問題,只是新的問題解了,又來了一個新的問題了,我有寫一支模擬user 上線時的流量測試,當server 那支程式剛開時,我的模擬user程式可以將近70 支程式在送封包給 server ,server 就是我在問的有關thread 問題的這支程式,當模擬user70人一直連繼上線一小時後,我發現我的server 那支程式開使lag了,接著慢慢的,user 這邊開使通知有封包 lost 掉了,後來user 程式只能降到接受50個,不然會一直lost,而server 端也越來越慢,而程式在 thread 那部份的寫法,是跟lu兄您說的差不多的,而server 只要重開了一次,那user端的流量又可以層加回到70支,請問這是為何呢?是否代表著,當thread 開啟後,不一定每一個thread 最後都會被清掉呢?所以時間一久,電腦資源就暫盡了,所以才導致越來越lag呢,甚至還會 lost 掉封包呢??小弟在thread 的處理部份,跟上一封我對lu兄發問的一樣,如下: __fastcall thread::thread(bool CreateSuspended, char *tBuffer,AnsiString FIP, int Port) : TThread(CreateSuspended) { memset(szBuffer, 0, sizeof(szBuffer)); memcpy(szBuffer, tBuffer, 1024); from_ip=FIP; from_port=Port; FreeOnTerminate=true; Resume(); } 我現在來去改成 lu兄您上一封說的那個樣子,看看lag問題會否再出現!謝謝您們幾位前輩的指引,謝謝!
pwipwi
版主


發表:68
回覆:629
積分:349
註冊:2004-04-08

發送簡訊給我
#15 引用回覆 回覆 發表時間:2004-12-30 17:42:35 IP:211.76.xxx.xxx 未訂閱
smartboss你好: 就你新的問題看起來,很像是有memory leak的樣子。可能有一些配置的記憶體沒有delete。這個方面就比較難解決,除了重新檢視程式碼以外,可以的解決方法不多。之前版上提到的解決是過一段時間就自動重開server程式...不過這還是下下之策。
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#16 引用回覆 回覆 發表時間:2004-12-30 17:51:29 IP:211.76.xxx.xxx 未訂閱
引言: smartboss你好: 就你新的問題看起來,很像是有memory leak的樣子。可能有一些配置的記憶體沒有delete。這個方面就比較難解決,除了重新檢視程式碼以外,可以的解決方法不多。之前版上提到的解決是過一段時間就自動重開server程式...不過這還是下下之策。
pwipwi 兄,您好,依您這樣說的話那是跟 thread 的配置方面問題可能無關,那我先來去找找看程式中是否有未free掉的東西,謝謝您的提醒。
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#17 引用回覆 回覆 發表時間:2004-12-30 18:11:18 IP:221.169.xxx.xxx 未訂閱
引言: lu 兄,您的意思這樣小弟董了,pwipwi 兄,同時也謝謝您,您也同時提到這個問題,只是新的問題解了,又來了一個新的問題了,我有寫一支模擬user 上線時的流量測試,當server 那支程式剛開時,我的模擬user程式可以將近70 支程式在送封包給 server ,server 就是我在問的有關thread 問題的這支程式,當模擬user70人一直連繼上線一小時後,我發現我的server 那支程式開使lag了,接著慢慢的,user 這邊開使通知有封包 lost 掉了,後來user 程式只能降到接受50個,不然會一直lost,而server 端也越來越慢,而程式在 thread 那部份的寫法,是跟lu兄您說的差不多的,而server 只要重開了一次,那user端的流量又可以層加回到70支,請問這是為何呢?是否代表著,當thread 開啟後,不一定每一個thread 最後都會被清掉呢?所以時間一久,電腦資源就暫盡了,所以才導致越來越lag呢,甚至還會 lost 掉封包呢??
上述的情形,偶想得到有2個 1. 就是跟pwipwi大大說的一樣,memory leak的問題,你可藉由WINDOWS的工作管理員,監視該程式所佔用的記憶體,看他是否越佔越多 2. 偶若沒猜錯,你SERVER的程式在接收USER登入之後,必須透過網路送一些訊息,給USER的程式,粉有可能瓶頸是在這部分,建議你先將送資料這部分先關掉(就是只接收訊息,不送資料出去),先測測看 一般來說程式LAG就是你的MAIN THREAD被佔用太久了,可能是Synchronize()這部分佔太久時間了,你可以在程式中計算一下,每次執行Synchronize()需要多少時間,看是不是會越來越久 以上一點小小的意見,希望對你有幫助 ========================= 大家一起快樂寫程式
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#18 引用回覆 回覆 發表時間:2004-12-30 21:36:41 IP:211.76.xxx.xxx 未訂閱
引言: 上述的情形,偶想得到有2個 1. 就是跟pwipwi大大說的一樣,memory leak的問題,你可藉由WINDOWS的工作管理員,監視該程式所佔用的記憶體,看他是否越佔越多 2. 偶若沒猜錯,你SERVER的程式在接收USER登入之後,必須透過網路送一些訊息,給USER的程式,粉有可能瓶頸是在這部分,建議你先將送資料這部分先關掉(就是只接收訊息,不送資料出去),先測測看 一般來說程式LAG就是你的MAIN THREAD被佔用太久了,可能是Synchronize()這部分佔太久時間了,你可以在程式中計算一下,每次執行Synchronize()需要多少時間,看是不是會越來越久 以上一點小小的意見,希望對你有幫助
lu 兄您好:您所說的第一點,我清楚,來去查查看,只是您所說的第二點,粽小弟實在有點模糊,為何說如果server 程式收了訊息處理後又送出去,這樣會到最後導致lag 呢?能否就這一部份教導一下小弟這是什麼原因造成的呢? 謝謝您那一點小小的意見,但是對我來說「死當的程式不過年,明年就可以過好年了」呵呵呵~~~ 謝謝您~~~
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#19 引用回覆 回覆 發表時間:2004-12-31 09:32:16 IP:221.169.xxx.xxx 未訂閱
引言: lu 兄您好:您所說的第一點,我清楚,來去查查看,只是您所說的第二點,粽小弟實在有點模糊,為何說如果server 程式收了訊息處理後又送出去,這樣會到最後導致lag 呢?能否就這一部份教導一下小弟這是什麼原因造成的呢?
SORRY 偶沒說清楚,假設你是使用UDP來傳送訊息,當你有70個CLIENT連線進來,那代表你你同一時間,就要傳送70個訊息出去,那如果你是使用的元件是同步傳送(就是當你下達SEND的指令時,會等到將資料傳送完畢後,程式的控制權才會再回來),那當你同一時間傳送的資料越多,那LAG的情況就越嚴重,因為要排隊等別的CLIENT送完,當然這是偶的猜測 關於這點,小弟一時之間,還沒想出好方法,唯一想出的方法,就是在THREAD之中產生UDP的元件,然後直接在THREAD之中傳送資料(不是在Synchronize()之中傳送喔),當然你必須確定,你使用的UDP元件必須能在MULTI THREAD之中運作 ========================= 大家一起快樂寫程式
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#20 引用回覆 回覆 發表時間:2004-12-31 13:10:30 IP:211.76.xxx.xxx 未訂閱
引言:
引言: lu 兄您好:您所說的第一點,我清楚,來去查查看,只是您所說的第二點,粽小弟實在有點模糊,為何說如果server 程式收了訊息處理後又送出去,這樣會到最後導致lag 呢?能否就這一部份教導一下小弟這是什麼原因造成的呢?
SORRY 偶沒說清楚,假設你是使用UDP來傳送訊息,當你有70個CLIENT連線進來,那代表你你同一時間,就要傳送70個訊息出去,那如果你是使用的元件是同步傳送(就是當你下達SEND的指令時,會等到將資料傳送完畢後,程式的控制權才會再回來),那當你同一時間傳送的資料越多,那LAG的情況就越嚴重,因為要排隊等別的CLIENT送完,當然這是偶的猜測 關於這點,小弟一時之間,還沒想出好方法,唯一想出的方法,就是在THREAD之中產生UDP的元件,然後直接在THREAD之中傳送資料(不是在Synchronize()之中傳送喔),當然你必須確定,你使用的UDP元件必須能在MULTI THREAD之中運作
lu 兄,我快陣亡了,簡直是時運不濟,我們上面討論的可能不是我現在的當務之急了,我昨天在公司裡的測試機測了一整天喔,完全安然無樣,想說大約十一十二點上線人數比較少時掛到真的對外主機,沒想到一掛上去不到五分鐘就掛了,掛的原因不清楚,掛的地方是在測試機也有跑過的程式段,掛的方式很像寫組合語言時當我們堆疊沒有做好return之後回跳的別的地方的情形很像,它是在做了一段sql 的查詢之後,程式就跳到一個條件不成立的地方去做運算而記然條件都不成立所有的變數都為0,結果一除就死掉了,這種bug 我寫c以來沒見過半次,lu 兄您有這樣的經驗嗎??昨天搞到4點多才回家,最後還是找不出原因來?
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#21 引用回覆 回覆 發表時間:2004-12-31 13:50:51 IP:221.169.xxx.xxx 未訂閱
引言: lu 兄,我快陣亡了,簡直是時運不濟,我們上面討論的可能不是我現在的當務之急了,我昨天在公司裡的測試機測了一整天喔,完全安然無樣,想說大約十一十二點上線人數比較少時掛到真的對外主機,沒想到一掛上去不到五分鐘就掛了,掛的原因不清楚,掛的地方是在測試機也有跑過的程式段,掛的方式很像寫組合語言時當我們堆疊沒有做好return之後回跳的別的地方的情形很像,它是在做了一段sql 的查詢之後,程式就跳到一個條件不成立的地方去做運算而記然條件都不成立所有的變數都為0,結果一除就死掉了,這種bug 我寫c以來沒見過半次,lu 兄您有這樣的經驗嗎??昨天搞到4點多才回家,最後還是找不出原因來?
你的錯誤~~~偶好眼熟阿,偶剛開始寫Multi Thread程式的時候也是跟你一樣,程式亂跑、亂當,偶抓這個BUG整整抓了2、3個月,後來發現是『重複進入』(reenter) ,簡單說就是Synchronize( ReadData ), 中ReadData FUNCTION,會有重複進入的情形(就是上一次還沒執行完,下一個又跑進來,鼻要問偶為啥會這樣,偶也搞不懂.....照理講使用 Synchronize() 應該會處理這樣的事,單是偶就是發生,為了抓這個BUG偶還特地帶了所有『機司』到客戶那邊,用BCB直接RUN來DEBUG....),解決方法粉簡單,用一個Mutex來做管制
__fastcall thread::thread(bool CreateSuspended, char *tBuffer,AnsiString FIP, int Port)
: TThread(CreateSuspended)
{

MutexObject = CreateMutex (NULL,false,"Test_SyncoObj");  //加上這一行    }    __fastcall thread::~thread()
{    //加上下面的程式碼
WaitForSingleObject (MutexObject,10000);
CloseHandle (MutexObject);    }    void __fastcall thread::Execute()
{     WaitForSingleObject(MutexObject,INFINITE);    Synchronize(ReadPacket);    ReleaseMutex (MutexObject);    }    
這是偶當初的解決方式,你試試看吧 還有在你修改程式之前,請你先檢查一下你的程式碼,鼻要THREAD之中『直接』操作任何VCL,所謂的直接如下
void __fastcall thread::Execute()
{ 

Edit1->Text = "test";   //這就叫做直接操作,在Synchronize內的則不算    Synchronize(ReadPacket);
}
當然不是所有的VCL都不能用,有些是可以的,偶一時之間無法詳舉.... 注意!!這點粉重要,若有『直接』操作任何VCL,粉容易導致不明原因當機(就是你說的那種情形) 一點點小心得,希望對你有幫助< > 加油成功就在眼前< >< >< > ========================= 大家一起快樂寫程式
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#22 引用回覆 回覆 發表時間:2004-12-31 14:16:10 IP:211.76.xxx.xxx 未訂閱
引言: 解決方法粉簡單,用一個Mutex來做管制
__fastcall thread::thread(bool CreateSuspended, char *tBuffer,AnsiString FIP, int Port)
: TThread(CreateSuspended)
{

MutexObject = CreateMutex (NULL,false,"Test_SyncoObj");  //加上這一行    }    __fastcall thread::~thread()
{    //加上下面的程式碼
WaitForSingleObject (MutexObject,10000);
CloseHandle (MutexObject);    }    void __fastcall thread::Execute()
{     WaitForSingleObject(MutexObject,INFINITE);    Synchronize(ReadPacket);    ReleaseMutex (MutexObject);    }    
這是偶當初的解決方式,你試試看吧 還有在你修改程式之前,請你先檢查一下你的程式碼,鼻要THREAD之中『直接』操作任何VCL,所謂的直接如下
void __fastcall thread::Execute()
{ 

Edit1->Text = "test";   //這就叫做直接操作,在Synchronize內的則不算    Synchronize(ReadPacket);
}
lu 兄:我先從後面請教您的問題, >> Edit1->Text = "test"; //這就叫做直接操作,在Synchronize內的則不算 我確定在thread 呼叫之後,在Synchronize之前並沒有做這樣的操作。 >>MutexObject = CreateMutex (NULL,false,"Test_SyncoObj"); //加上這一行 請問一下MutexObject型態是什麼呢??,我找到一個叫HANDLE 是用這個型態宣告的對嗎? 還有 "Test_SyncoObj" 是要寫Synchronize(ReadPacket) 裡的readpacket 嗎??或者就寫 Test_SyncoObj 這樣就行呢? >>WaitForSingleObject (MutexObject,10000); 還有請問這個func 的最後 10000 是代表什麼意思呢? lu 兄感謝您常常給的一點點,但是卻是我的一大點! 發表人 - smartboss 於 2004/12/31 14:21:55
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#23 引用回覆 回覆 發表時間:2004-12-31 15:34:23 IP:211.76.xxx.xxx 未訂閱
引言:
引言: lu 兄,我快陣亡了,簡直是時運不濟,我們上面討論的可能不是我現在的當務之急了,我昨天在公司裡的測試機測了一整天喔,完全安然無樣,想說大約十一十二點上線人數比較少時掛到真的對外主機,沒想到一掛上去不到五分鐘就掛了,掛的原因不清楚,掛的地方是在測試機也有跑過的程式段,掛的方式很像寫組合語言時當我們堆疊沒有做好return之後回跳的別的地方的情形很像,它是在做了一段sql 的查詢之後,程式就跳到一個條件不成立的地方去做運算而記然條件都不成立所有的變數都為0,結果一除就死掉了,這種bug 我寫c以來沒見過半次,lu 兄您有這樣的經驗嗎??昨天搞到4點多才回家,最後還是找不出原因來?
lu 兄我有使用您剛才教我的方法了,可是以上的情況依然會發生,我確定判斷沒有錯誤,也確定它是突然就跳到別的地方去跑程式段,但是就是無法避免掉它,我都不知道該從何查起,只知道它都在同一個地方附近跳掉,且知道它總是跳到同一個地方去,??能再教一下小弟下一步該怎麼做嗎??
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#24 引用回覆 回覆 發表時間:2004-12-31 16:21:20 IP:221.169.xxx.xxx 未訂閱
引言: >>MutexObject = CreateMutex (NULL,false,"Test_SyncoObj"); //加上這一行 請問一下MutexObject型態是什麼呢??,我找到一個叫HANDLE 是用這個型態宣告的對嗎? 還有 "Test_SyncoObj" 是要寫Synchronize(ReadPacket) 裡的readpacket 嗎??或者就寫 Test_SyncoObj 這樣就行呢? >>WaitForSingleObject (MutexObject,10000); 還有請問這個func 的最後 10000 是代表什麼意思呢?
MutexObject 的型態為HANDLE,"Test_SyncoObj"為一判別字串,你可以任意寫 >>WaitForSingleObject (MutexObject,10000); 還有請問這個func 的最後 10000 是代表什麼意思呢? TIMEOUT 的時間
引言: lu 兄我有使用您剛才教我的方法了,可是以上的情況依然會發生,我確定判斷沒有錯誤,也確定它是突然就跳到別的地方去跑程式段,但是就是無法避免掉它,我都不知道該從何查起,只知道它都在同一個地方附近跳掉,且知道它總是跳到同一個地方去,??能再教一下小弟下一步該怎麼做嗎??
呼~~粉抱歉,偶沒幫上你的忙.... 讓偶分析一下你程式出錯的狀況,你看看對不對 > > >大家一起快樂寫程式
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#25 引用回覆 回覆 發表時間:2004-12-31 16:28:32 IP:211.76.xxx.xxx 未訂閱
引言:
引言:
引言: lu 兄,我快陣亡了,簡直是時運不濟,我們上面討論的可能不是我現在的當務之急了,我昨天在公司裡的測試機測了一整天喔,完全安然無樣,想說大約十一十二點上線人數比較少時掛到真的對外主機,沒想到一掛上去不到五分鐘就掛了,掛的原因不清楚,掛的地方是在測試機也有跑過的程式段,掛的方式很像寫組合語言時當我們堆疊沒有做好return之後回跳的別的地方的情形很像,它是在做了一段sql 的查詢之後,程式就跳到一個條件不成立的地方去做運算而記然條件都不成立所有的變數都為0,結果一除就死掉了,這種bug 我寫c以來沒見過半次,lu 兄您有這樣的經驗嗎??昨天搞到4點多才回家,最後還是找不出原因來?
lu 兄我有使用您剛才教我的方法了,可是以上的情況依然會發生,我確定判斷沒有錯誤,也確定它是突然就跳到別的地方去跑程式段,但是就是無法避免掉它,我都不知道該從何查起,只知道它都在同一個地方附近跳掉,且知道它總是跳到同一個地方去,??能再教一下小弟下一步該怎麼做嗎?? < face="Verdana, Arial, Helvetica"> lu 兄,小弟找出問題點了,終於解決問題了,原來是我修改的thread 的宣告方式之後,它成為了一個獨立的個体,而我忘了這個原則,而繼用之前的共用變數,之前的程式thread 一開它裡面用了很多在main程式段裡就給的全域共用變數,而現在的是把thread 與 main 的全部分開,所以當thread 裡面有用到之前與全域變數同名的現在都己不再是全域,而是在thread class裡,這樣的結果就是這個變數將會是為0,而我卻一直以為是全域變數的值所倒致,只是我覺得很怪的是我程式裡有用try and catch 來追蹤,而在try 裡的每一行我都用一個 int fl; 的變數去编號,例子如下: fl=1; if(XXX ) { abc = dec; fl=2; callfunc(); fl=3; } 但是為何當我的程式當發生錯誤跳到 catch 去提警時,我看到的fl 的行數,並不是造成 EDivByZero (變數/0)的地方呢?? 而是離它很遠的地方,使我一直 被誤導以為是程式亂跳,請問 lu 兄這又是什麼原因造成呢??
lu
高階會員


發表:11
回覆:189
積分:195
註冊:2003-11-19

發送簡訊給我
#26 引用回覆 回覆 發表時間:2004-12-31 16:38:50 IP:221.169.xxx.xxx 未訂閱
引言: lu 兄,小弟找出問題點了,終於解決問題了,原來是我修改的thread 的宣告方式之後,它成為了一個獨立的個体,而我忘了這個原則,而繼用之前的共用變數,之前的程式thread 一開它裡面用了很多在main程式段裡就給的全域共用變數,而現在的是把thread 與 main 的全部分開,所以當thread 裡面有用到之前與全域變數同名的現在都己不再是全域,而是在thread class裡,這樣的結果就是這個變數將會是為0,而我卻一直以為是全域變數的值所倒致,只是我覺得很怪的是我程式裡有用try and catch 來追蹤,而在try 裡的每一行我都用一個 int fl; 的變數去编號,例子如下: fl=1; if(XXX ) { abc = dec; fl=2; callfunc(); fl=3; } 但是為何當我的程式當發生錯誤跳到 catch 去提警時,我看到的fl 的行數,並不是造成 EDivByZero (變數/0)的地方呢?? 而是離它很遠的地方,使我一直 被誤導以為是程式亂跳,請問 lu 兄這又是什麼原因造成呢??
哇~~恭喜、恭喜~~給你拍拍手、給你鼓鼓掌< > 至於你的問題,偶真的不知如何回答......因為偶真的無法猜測,程式在發生錯誤的當時,會出現啥狀況 你這樣的問題,好像在問車商,如果偶開你的車車去撞電線桿,那是哪個零件會壞掉.....< >呵呵~~有點爛的比喻 不管怎麼樣,恭喜你抓到BUG,這下應該可以陪妹妹去跨年了喔 ========================= <>大家一起快樂寫程式
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#27 引用回覆 回覆 發表時間:2004-12-31 17:40:46 IP:211.76.xxx.xxx 未訂閱
引言: 呼~~粉抱歉,偶沒幫上你的忙.... 讓偶分析一下你程式出錯的狀況,你看看對不對 > > >< face="Verdana, Arial, Helvetica"> lu 兄請您不要這麼說,您迪確幫了小弟不少的忙,我先把這次的案子結了抓程式lag 的問題我再開一個來請教您,您這一次提到的這幾個問題我想小弟可能只是尚未遇到而己,我想搞不好會有機會遇到,其實這支程式是人家別的公司己經不維護了才「送」說好聽些是「送」給我們公司,說難聽些是「倒」給我們公司來然後要我們自己維修,自己用,結果是問題百出且三不五時當機是正常的,還好遇到了您的協助,而最大的難題將來,如果這支程式依我的測試流量跟操它的實用性都己經出來了,所以極有可能公司如果覺得己經有這種穩定的技術時,恐怕會棄那支舊source 然後重新規劃開發一支新的授權系統,所以可能自己寫時有可能就會遇到您所說的問題,其實我最怕的不外就是您所提的第2個問題「可能是資料庫物件操作所導致(鼻要懷疑,這個偶個人常常遇到,程式碼看起來OK,一旦大量、密集運作就掛)」到時可能還有得搞因為,重寫將不再使用bde,而是改採ado的方式進行,小弟還是一句話送給lu兄,及站上有幫小弟解題的前輩們pwipwi 及dllee 們,向您們說聲十二萬分的感謝您們的幫助。 小小的謝意,希望各位前輩不要介意。
dllee
站務副站長


發表:319
回覆:2516
積分:1710
註冊:2002-04-15

發送簡訊給我
#28 引用回覆 回覆 發表時間:2004-12-31 22:40:15 IP:211.76.xxx.xxx 未訂閱
恭喜!恭喜! Happy New Year!!  >) 您說的<>< face="Verdana, Arial, Helvetica">引言:你的錯誤~~~偶好眼熟阿,偶剛開始寫Multi Thread程式的時候也是跟你一樣,程式亂跑、亂當,偶抓這個BUG整整抓了2、3個月,後來發現是『重複進入』(reenter) ,簡單說就是Synchronize( ReadData ), 中ReadData FUNCTION,會有重複進入的情形(就是上一次還沒執行完,下一個又跑進來,鼻要問偶為啥會這樣,偶也搞不懂.....照理講使用 Synchronize() 應該會處理這樣的事,單是偶就是發生 我之前也有遇過相同的問題...但之前您沒有提過,所以我以為是 Critical Section 有問題... 因為我是一律都 Synchronize,按理說都應該只在主執行緒中執行,也應該不會有重入的現象,但是當 Synchronize 內有處理到(BDE)資料庫時,就有可能在一個還沒執行完又另一個再進來。而第一次是使用 Critical Section 把所有資料庫的操作都作保護,似乎沒事了一段時間(也有好幾個月),但之後又發生 Application->ProcessMessage() 的事件...(就是之前提問的執行緒問題)。 有機會的話,還是要把 BDE 換掉!! 目前就在開發自家用的簡易資料庫,不用 BDE 也不用 ADO 全部自己來,反正我要的資料庫的功能非常簡單,只用到 BDE/ADO 的萬分之一的功能,卻得為它們的不穩定性或不確定性擔心... 改天會試試您的 Mutex 的方法,看是否在 Synchronize 狀況下,其他的程式碼就不需要 Critical Section 也不用擔心重入了,感謝分享 < href="http://free.greenworld.com.tw/~dllee/" target="blank">吃軟也吃硬 dllee.ktop.com.tw StatPlus 系統資源監測器 @ KTOP VMASK - ViewMove Automation Software Kernel
------
http://blog.yam.com/dllee/
conundrum
尊榮會員


發表:893
回覆:1272
積分:638
註冊:2004-01-06

發送簡訊給我
#29 引用回覆 回覆 發表時間:2005-01-01 22:47:26 IP:220.143.xxx.xxx 未訂閱
http://www.delphi3d.net/articles/viewarticle.php?article=threads.htm
dllee
站務副站長


發表:319
回覆:2516
積分:1710
註冊:2002-04-15

發送簡訊給我
#30 引用回覆 回覆 發表時間:2005-01-02 17:46:42 IP:211.76.xxx.xxx 未訂閱
感謝 conundrum 大大提供的好文章  我把它提供的範例改成 > < href="http://free.greenworld.com.tw/~dllee/" target="blank">吃軟也吃硬 dllee.ktop.com.tw StatPlus 系統資源監測器 @ KTOP VMASK - ViewMove Automation Software Kernel
------
http://blog.yam.com/dllee/
smartboss
初階會員


發表:19
回覆:93
積分:42
註冊:2004-12-29

發送簡訊給我
#31 引用回覆 回覆 發表時間:2005-01-02 17:55:07 IP:210.192.xxx.xxx 未訂閱
引言: http://www.delphi3d.net/articles/viewarticle.php?article=threads.htm
感謝 conundrum 兄,您提供的這編文章,小弟想您這編文章貇定能像lu 兄一樣,為站上的朋友帶來不少解決問題的辦法,非常的感謝您! 一點點謝意,請笑納。
[<<] [1] [2] [>>]
系統時間:2017-10-17 21:10:18
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!