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

什麼是 Thread-Safe 及如何測試?

答題得分者是:lu
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-05-09 09:03:23 IP:211.76.xxx.xxx 訂閱
Thread-Safe 網路上找到的資料: http://whatis.techtarget.com/definition/0,,sid9_gci331590,00.html
引言: thread-safe In computer programming, thread-safe describes a program portion or routine that can be called from multiple programming threads without unwanted interaction between the threads. (A thread is an instance of the program running on behalf of some user or process.) Thread safety is of particular importance to Java programmers, since Java is a programming language that provides built-in support for threads. By using thread-safe routines, the risk that one thread will interfere and modify data elements of another thread is eliminated by circumventing potential data race situations with coordinated access to shared data. It is possible to ensure that a routine is thread-safe by: 1. Making sure that concurrent threads use synchronized algorithms that cooperate with each other. 2. Confining the address of a shared object to one thread whenever an unsynchronized algorithm is active.
還有: http://www.artima.com/designtechniques/threadsafety.html http://www.google.com/search?hl=zh-TW&ie=UTF-8&oe=UTF-8&q=THREAD+SAFE+VCL&lr= 我的問題是,我如何確認自己寫的函式或元件是不是 Thread-Safe? 有沒有辨法可以測試別人的函式或元件是不是 Thread-Safe? 沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-05-09 20:08:38 IP:211.76.xxx.xxx 訂閱
from BCB5 online Help Using the main VCL thread
引言: You do not always need to use the main VCL thread. Some objects are thread-aware. Omitting the use of the Synchronize method when you know an object? methods are thread-safe will improve performance because you don急 need to wait for the VCL thread to enter its message loop. You do not need to use the Synchronize method in the following situations:
  • Data access components are thread-safe as follows: For BDE-enabled datasets, each thread must have its own database session component. The one exception to this is when you are using Access drivers, which are built using a Microsoft library that is not thread-safe. ADO and InterbaseExpress components are thread-safe. When using data access components, you must still wrap all calls that involve data-aware controls in the Synchronize method. Thus, for example, you need to synchronize calls that link a data control to a dataset by setting the DataSet property of the data source object, but you don急 need to synchronize to access the data in a field of the dataset. For more information about using database sessions with threads in BDE-enabled applications, see Managing multiple sessions.
  • Graphics objects are thread-safe. You do not need to use the main VCL thread to access TFont, TPen, TBrush, TBitmap, TMetafile, or TIcon. Canvas objects can be used outside the Synchronize method by locking them.
  • While list objects are not thread-safe, you can use a thread-safe version, TThreadList, instead of TList.
沒空更新的網頁... http://dllee.ktop.com.tw C及指標教學,計算機概論,資訊管理導論... http://dllee.adsldns.org 介紹Shells,LiteStep,GeoShell....
------
http://www.ViewMove.com
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-06-04 13:37:29 IP:220.139.xxx.xxx 訂閱
是否只要在主執行緒(main VCL thread)內執行就是 Thread-Safe 呢? 除了 Synchronize() 還有其他的方法可以讓執行緒內的操作在主執行緒內執行嗎? 因為我所用的 3rd party 元件內有使用執行緒,但是使用 tdump 查看它的 Import Function List 沒有 __fastcall Classes::TThread::Synchronize(void __fastcall __closure(*)()) 這一項,而我自己寫的執行緒有用 Synchronize() 會有上述的 Import Function,而 3rd party 元件公司技術客服表示他們的元件是 Thread-Safe 所有的事件會是在主執行緒內執行。    但以我目前所知,我只會使用 Synchronize() ,不知道是否還有其他的方法可以讓執行緒內所觸發的事件在主執行緒內執行?    http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc.
------
http://www.ViewMove.com
hao_chih
一般會員


發表:15
回覆:25
積分:18
註冊:2003-09-10

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-06-04 18:19:16 IP:61.63.xxx.xxx 未訂閱
dllee版大您好~你的問題真難^^"都沒人敢回答~    我再Borland的網站上有找到一篇文章~不知是否對您有用~供您參考~    
 
Tilte:Synchronising Component events with the main VCL threads    Summary: Component events are not synchronized with the main VCL 
         thread when used in multithreaded applications. This sample 
         shows how to do it, regardless of event type.     Description: Using a component in a multithreaded application needs 
             additional work to make it thread safe. In particular, 
             the events of the component need to be synchronized with 
             the main VCL thread. Although work needs to be added for 
             each event in the component, the method of achieving 
             full synchronization is quite easy once you know how. 
             This sample provides a demo component to weakly encrypt 
             a file. The work is performed in a worker thread. The 
             demonstration program provided allows you to choose a 
             directory and have all the files encrypted using the one 
             component. A semaphore is used to limit the number of 
             running threads. Each file has a dynamically created 
             progress bar added to a scrollbox. This progress bar is 
             then updated as each file is encrypted. You can visually 
             see the progress of each thread, visually see how many 
             threads are running and how many are waiting. As each 
             thread completes, the progress bar is removed from the 
             scrollbox.     Product: C++Builder (3-6) Source Code 
Contest: Multithreaded programming 
檔案我已經下載試看看過了,所以順便把他上傳到這~方便您看看是否有用~ http://delphi.ktop.com.tw/loadfile.php?TOPICID=16055661&CC=359079 順心~
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-06-05 09:21:39 IP:211.76.xxx.xxx 訂閱
感謝 hao_chih 的回應 < > 這個問題確實很難 (至少我就是不會,不然也不會提問 < > ) 不過,大家還是可以討論討論 您提供的範例我下載了也看過了,其中所用的方法就是 href="http://www.ViewMove.com">http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc. 發表人 - dllee 於 2004/06/05 09:44:51
------
http://www.ViewMove.com
allanchou
一般會員


發表:9
回覆:35
積分:8
註冊:2003-04-01

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-08-18 13:55:45 IP:61.30.xxx.xxx 未訂閱
Thread-Safe 我所知道是泛指, 某個變數在multi-thread中運作,不經Thread-safe技巧處理而造成程式錯誤.至於Synchronize(), 我很少用, 我都是用Critical Section來進行Thread-Safe,Synchronize()似乎也是應用Critical Section,只是把整個執行緒裡面的程式碼全部用一個Critical Section包起來, (這點我並不確定, 只是印象中好像是這樣) Critical Section的用法, 通常我是用最短原則(C-S 區段保護的程式不要太長). 3rd 元件我不常用, 不過預期最近應該會遇到(Thread中跑 TurboPower XMLpartner), 我很怕Event在thread中會有lost. 還有我覺得Synchronize(),應該不是把WorkThread的工作交由Mainthread來做, 因為只有一個CPU, 應該是暫停其中一條Thread, 讓另一條Thread工作.(書上有說, 可惜手邊這本書不在)
lu
高階會員


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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-08-18 14:56:27 IP:221.169.xxx.xxx 未訂閱
引言: 還有我覺得Synchronize(),應該不是把WorkThread的工作交由Mainthread來做, 因為只有一個CPU, 應該是暫停其中一條Thread, 讓另一條Thread工作. 好像不對喔,Borland的TTHread物件是在CREATE的時候,在內部產生一個WINDOW,當使用者呼叫 Synchronize()時,是利用SendMesage 的方式讓程式返回MAINTHREAD來執行,驗證方法很簡單,各位在呼叫 Synchronize()將程式停下來,然後按CTRL + ALT + T觀看目前是在哪一個THREAD 有興趣的大大可以看一下TThread 的SOURCE,檔案在C:\Program Files\Borland\CBuilder5\Source\Vcl\classes.pas
引言: 您提供的範例我下載了也看過了,其中所用的方法就是 Synchronize() 我只是想確認是否有其他的方法,如果 Synchronize() 是唯一的方法,那也這算是本題的解答呀,只是... 是否真的只有 Synchronize() 呢? 有誰能很確定的告訴我。 ㄟ...當然不只一種方法,例如你在THREAD中丟一個Message(利用SendMessage or PostMessage)給MAINTHREAD(也就是ACTIVE FORM啦),讓MainThread執行某些事,這也是一招啦,這招就是偶在寫M$ VC 時所用的方法 但是ㄋ.....有>< face="Verdana, Arial, Helvetica"> 最後~~提一下所謂的Thread-saft 是指你可以在任意一個THREAD中呼記 OR 使用該物件 OR FUNCTION喔,如果是利用Synchronize(),那偶個人認為應該不算THREAD-SAFT喔 至於如何測試,一個 > ========================= <>大家一起快樂寫程式
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-08-19 08:41:57 IP:211.76.xxx.xxx 訂閱
感謝 allanchou 及 lu 的回應。 我因為專案一定要用到別人的元件,但是在使用上就是有問題, 問了廠商,廠商自然是說,我們的元件是 Thread-Safe 的... 但我們沒有原始碼,實在是不知道它到底是如何寫的, 所以我才使用了 tdump 查看它的 Import Function List。    如果,按 allanchou 所說,不用 TThread::Synchronize() 可以用 Critical Section 的方式... 是像我們在使用元件時,如果它有提供事件,那個事件是由使用者(也就是我)來寫的,使用者要如何寫,寫元件的人並無法預期,如此,還會使用 Critical Section 嗎? 大部分我看到在元件中叫用事件會以 Synchronize() 所以,我才想,是否應該只會用 Synchronize()...    如果,按 lu 所說,可以用 post message 的方式... 那是否在 VCL 的架構中,在寫有執行緒元件時,還是得用 Synchronize() 呢? 還是說有其他的技巧?    以我目前遇到的狀況是,使用 3rd party VCL 元件,那個元件是作網路連線/通訊用的,它使用多執行緒處理每一個 communication transaction,在處理的過程,會觸發事件,如:已連線/已斷線/開始傳訊/已傳訊完成/接受訊息/結束傳訊/傳訊過程異常... 等等的事件,在這些事件中,我會寫我所需要的處理程式(當然,不會再開執行緒,只是一般的 C++ 語法處理)。    視動科技 VMASK - ViewMove Automation Software Kernel
------
http://www.ViewMove.com
lu
高階會員


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

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-08-19 09:37:33 IP:221.169.xxx.xxx 未訂閱
引言: 我因為專案一定要用到別人的元件,但是在使用上就是有問題, 問了廠商,廠商自然是說,我們的元件是 Thread-Safe 的... 但我們沒有原始碼,實在是不知道它到底是如何寫的,
還.....真是....負責任的說法阿 <>< face="Verdana, Arial, Helvetica">引言: 不用 TThread::Synchronize() 可以用 Critical Section 的方式... 是像我們在使用元件時,如果它有提供事件,那個事件是由使用者(也就是我)來寫的,使用者要如何寫,寫元件的人並無法預期,如此,還會使用 Critical Section 嗎? 大部分我看到在元件中叫用事件會以 Synchronize() 所以,我才想,是否應該只會用 Synchronize()... ㄟ...不管是使用 Critical Section, Mutex , 還是Event ,基本上你還是在另外一個 THREAD 中使用該物件喔,除非你是使用 Synchronize() , Synchronize()是把程式的執行權切回 MainThread 中來執行你的程式.... 不管是使用 Critical Section, Mutex 還是 Event,基本上你可以把當成,像是紅綠燈的東西(偶知道這個說法不恰當),你可以在不同的Thread中,鎖定(紅燈)或是釋放(綠燈)Critical Section, Mutex 還是 Event,以達到某些目的(例如同一時間,有2個以上的THREAD去改變,某個變數 OR 資料) 你說的物件,所產生的事件,是不是要用Critical Section 還是要用Synchronize(),這個問題粉簡單,端看你在該事件當中,是不是有用到非Thread Safe 的物件 OR FUNCTION(順帶提一下,BORLAND VCL中的可視元件,基本上都可視為非THREAD SAFT),如果沒有,那用Critical Section即可,不然還是用Synchronize()
引言: 如果,按 lu 所說,可以用 post message 的方式... 那是否在 VCL 的架構中,在寫有執行緒元件時,還是得用 Synchronize() 呢? 還是說有其他的技巧?
如果你是用BORLAND VCL來寫程式的話,當然是用Synchronize(),沒事幹嘛自己寫? 再提醒一次,寫 >) ... <>< face="Verdana, Arial, Helvetica">引言: 以我目前遇到的狀況是,使用 3rd party VCL 元件,那個元件是作網路連線/通訊用的,它使用多執行緒處理每一個 communication transaction,在處理的過程,會觸發事件,如:已連線/已斷線/開始傳訊/已傳訊完成/接受訊息/結束傳訊/傳訊過程異常... 等等的事件,在這些事件中,我會寫我所需要的處理程式(當然,不會再開執行緒,只是一般的 C 語法處理)。 是喔~~網路通訊的程式,那這個物件,本身就是Multi Thread了阿,你不用在其他的THREAD之中,來操作該物件,唯一要注意的是,當該物件產生事件時,你必須確定,是在哪一個THREAD之中,因為可能是其他的THREAD,也可能是MAIN THREAD,端看該物件怎麼寫 如果是其他的THREAD,偶建議你用 SendMessage() or PostMessage()的方式將程式切到MAIN THREAD來執行,因為偶猜該事件觸發時,你必須顯示某些訊息 當然如果是MAIN THREAD就不用那麼麻煩了 一點點建議,參考一下吧 ========================= 大家一起快樂寫程式
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2004-08-20 07:44:36 IP:211.76.xxx.xxx 訂閱
以下是我問此問題時,問 3rd party 廠商的問題及其回應:
引言:
我問 XXX 的問題:
*. We think there should be some threads running in XXX-Pack,
   and we may using VCL components in XXX-Pack event.
   Is there any restriction in programming the XXX-Pack event
   to make it thread-safe?
   Or is it possible to add the Synchronized property to using
   Synchronize() call to XXX-Pack event?
 
XXX 回應: 
   The entire XXX-Pack is thread safe: all the events run in the main
   thread, then there is no problem to use VCL.    我再追問:
*.About all XXX-Pack's events run in the main thread,
  I was wondering why the 
__fastcall Classes::TThread::Synchronize(void __fastcall __closure(*)())
  is not in the import function list of the XXX-Pack?
  In our system, we using Synchronize() in thread to let
  the event run in VCL main thread, and the TThread::Synchronize
  is in the import function list of our system.      We check it by
  C:\Windows\system32> tdump XXX-Pack.bpl XXX-Pack.lst
  and there is no TThread::Synchronize in XXX-Pack.lst.      Is there any other method to let the event run in main thread
  instead of Synchronize() ?
但廠商已沒回應。也就是因為這樣,我才想確認,是否在 VCL 的系統,只有 Synchronize() 才能讓事件在主執行緒中執行,也才能操作 VCL 可視或不可視的元件。 在我的系統中,除了使用此廠商元件外,其他都是自己寫的,也使用了自行開發的 ThreadTimer 元件,當然,我們是使用 Synchronize() 的方式來叫用 ThreadTimer 的事件,所以沒有發生問題,而在有使用該廠商元件的系統,平均 9~12 天就會發生不可預期的當機事件,而在當機時,我們的 LOG 系統也掛點,無法正常 LOG,所以連發生什麼事都不知道,只是每次發生當機前,該廠商元件就會有異常的 LOG,這才讓我懷疑是否是它造成的,為了找問題,我幾乎反組譯它的 .bpl 最後,廠商也還是沒回應,而我只能修改我的程式,在使用它的元件時要特別小心處理。 以目前我會使用的多緒防護也只有 > > href="http://www.ViewMove.com" target="blank">視動科技 VMASK - ViewMove Automation Software Kernel 發表人 - dllee 於 2004/08/20 07:49:40
------
http://www.ViewMove.com
lu
高階會員


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

發送簡訊給我
#11 引用回覆 回覆 發表時間:2004-08-20 10:46:34 IP:221.169.xxx.xxx 未訂閱
引言: 但廠商已沒回應。也就是因為這樣,我才想確認,是否在 VCL 的系統,只有 Synchronize() 才能讓事件在主執行緒中執行,也才能操作 VCL 可視或不可視的元件。
ㄟ...在 VCL 的系統,不是只有 Synchronize() 才能讓事件在主執行緒中執行,有粉多方法喔,舉各例子在M$ VC ,就沒有VCL,那他棉要怎麼用ㄋ?在BORLAND中如果你是用 TThread來寫Multi Thread的程式的話,『通常』會使用Synchronize()來進行將程式切回MAIN THREAD之中,當然~~當然~~條條大路通羅馬,當然有其他的方法,甚至搞不好有人不喜歡用BORLAND的TThread物件勒,原因無他,TThread比較耗費系統資源喔,因為TThread 為產生一個不可視的Handle,並利用這個Handle 來進行Synchronize()這個功能 看了一下,想問一件事,除了 ThreadTimer 之外你還有用其他的THREAD嗎?如果沒有,基本上你的程式,應該是屬於單執行緒的程式喔,所以,理論上應該不用考慮使用Synchronize()等相關事宜.... 至於你說,你的程式在RUN 9~12天之後就會掛了,偶猜可能是M$ 的OS撐不住了吧,檢查一下,你程式對記憶體的使用,是否有問題?是不是該DELETE沒DELTET等等 最後提各建議,偶之前寫的程式也是這樣,後來偶將程式中,所有會運用的記憶體的地方(用NEW向系統要求一對記憶體,用完即DELETE),全部改成,在程式一開始就向系統要求一大塊記憶體,然後在程式中不在使用NEW AND DELETE來產生新的記憶體....然後就好了 ========================= 大家一起快樂寫程式
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#12 引用回覆 回覆 發表時間:2004-08-21 22:03:29 IP:203.204.xxx.xxx 訂閱
基本上我所使用的 3rd party 元件是使用 VCL 的 TThread 來開執行緒的,其 import function list 有:
Imports from VCL50.BPL
__fastcall Classes::TThread::Terminate()
__fastcall Classes::TThread::SetPriority(Classes::TThreadPriority)
__fastcall Classes::TThread::DoTerminate()
__fastcall Classes::TThread::~TThread()
__fastcall Classes::TThread::TThread(bool)
__tpdsc__ Classes::TThread
Classes::TThread::
所以我能確定它有開執行緒,而且是使用 VCL 內的 TThread 元件,同時沒有使用到 TThread::Synchronize() 也就是因為這樣,我才會發那像的信給廠商。 另外,在我的 ThreadTimer 中如果不使用 Synchronize() 直接叫用 OnTimer 事件,而我在 OnTimer 操作畫面,沒多久就當機了,所以一定要使用 Synchronize(),並不是像您說的單執行緒喔,我的系統由工作管理員可以看到,同時有 50 多個執行緒在執行。 而 new/delete 的問題,是我最注重的,自然是沒有問題,而且大部分也是在表單建構元中都 new 出來,解構元再 delete。對於記憶體的使用量,我的系統也都一直在監視,連 new/delete 的次數都在監視範圍,基本上如果有發生 new 不 delete 的狀況,很容易就會發現。 在發現問題後看到異常的 LOG 才去 trace 3rd party 元件,發現它有用 TThread 但不使用 Synchronize() 所以,我才想確認是否有什麼方法可以不在 TThread 中不使用 Synchronize() 來叫用事件,同時能確保是 Thread Safe 的作法,而我也會試著去 trace 它是否是這樣的方法,否則,我實在不能確信它是 Thread Safe 的... 視動科技 VMASK - ViewMove Automation Software Kernel 發表人 - dllee 於 2004/08/21 22:04:41
------
http://www.ViewMove.com
pwipwi
版主


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

發送簡訊給我
#13 引用回覆 回覆 發表時間:2004-08-23 13:16:05 IP:211.76.xxx.xxx 未訂閱
雖然小弟對Thread所知有限,不過提一些地方作為大大們的參考。 在寫Thread的時候不用到Synchronize的是一個比較好的實作。(不用 Synchronize比較不會有bug,而且速度不會delay,能不用就不用) 將Thread實作與變數和介面碼完全的分離,完全當成兩個程式在寫。 最後再決定幾個公用變數,比如設一個log的物件,或一個int變數。是兩個程式碼可以看到的。 int的寫入和讀取是不怕重入的,所以不必考慮Thread重入的問題。 log物件就比較要注意,每個method都要考慮會不會有Thread與主程同時讀取的問題。如果在重入時會有運作的問題,就要設個Critical Section作管制。 上次我寫Thread時,是寫一個Backup server。方式也是indy的Thread和主程式介面完全分開。有一個AnsiString,是indy只能寫,主程式只能讀。(如果主程式也能寫入,就不保證是safe了....) 主程式可以經由這些變數知道Thread現在在update那一個檔案,做什麼動作。另外,log物件就要考慮重入,每個method設一個critical section。實作起來可以完全不要Synchronize,程式也比較stable,放上幾個月沒問題。 如果有地方是需要Thread等主程式做某件事完才continue的。以前我也會用Synchronize。不過後來我選擇利用共通的變數,由Thread通知主程式"我要停下來了!",主程式再主動的suspend Thread、處理事情、再restart Thread。也省下了Synchronize帶來的危險。 不過我現在對Thread最不熟的還是Thread中Exception的處理、Exception發生時變數釋放和程式重新運作的問題....Thread,果然是令人頭痛的東西。 發表人 - pwipwi 於 2004/08/23 13:19:30
lu
高階會員


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

發送簡訊給我
#14 引用回覆 回覆 發表時間:2004-08-23 13:43:44 IP:221.169.xxx.xxx 未訂閱
引言: 在寫Thread的時候不用到Synchronize的是一個比較好的實作。(不用 Synchronize比較不會有bug,而且速度不會delay,能不用就不用) 如果有地方是需要Thread等主程式做某件事完才continue的。以前我也會用Synchronize。不過後來我選擇利用共通的變數,由Thread通知主程式"我要停下來了!",主程式再主動的suspend Thread、處理事情、再restart Thread。也省下了Synchronize帶來的危險。
請問一下Synchronize() 有問題嗎?這是偶第一次聽說ㄝ,是不是請pwipwi 大大解說一下,如果是的話~~那偶麻煩大了,因為偶程式中都是用Synchronize()....拜託 <>< face="Verdana, Arial, Helvetica">引言: 將Thread實作與變數和介面碼完全的分離,完全當成兩個程式在寫。 最後再決定幾個公用變數,比如設一個log的物件,或一個int變數。是兩個程式碼可以看到的。 int的寫入和讀取是不怕重入的,所以不必考慮Thread重入的問題。 log物件就比較要注意,每個method都要考慮會不會有Thread與主程同時讀取的問題。如果在重入時會有運作的問題,就要設個Critical Section作管制。 上次我寫Thread時,是寫一個Backup server。方式也是indy的Thread和主程式介面完全分開。有一個AnsiString,是indy只能寫,主程式只能讀。(如果主程式也能寫入,就不保證是safe了....) 主程式可以經由這些變數知道Thread現在在update那一個檔案,做什麼動作。另外,log物件就要考慮重入,每個method設一個critical section。實作起來可以完全不要Synchronize,程式也比較stable,放上幾個月沒問題。 呵呵~~這也是偶第一次看到的方法.... 偶之前看了一些Multi - Thread的書,書上都是說,只要你的變數,會被2個(含)以上存、取,你就必須用 Mutex , Event or Critical Section來作為作管制, pwipwi 大大的方式,偶倒是第一次看到ㄝ,呵呵~~又學到一招 謝謝 pwipwi 大大的分享 ========================= 大家一起快樂寫程式
lu
高階會員


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

發送簡訊給我
#15 引用回覆 回覆 發表時間:2004-08-23 14:16:46 IP:221.169.xxx.xxx 未訂閱
引言: 在發現問題後看到異常的 LOG 才去 trace 3rd party 元件,發現它有用 TThread 但不使用 Synchronize() 所以,我才想確認是否有什麼方法可以不在 TThread 中不使用 Synchronize() 來叫用事件,同時能確保是 Thread Safe 的作法,而我也會試著去 trace 它是否是這樣的方法,否則,我實在不能確信它是 Thread Safe 的...
恩~~偶想你有點誤會你3RD廠商的意思嘍,所謂的那個物件是THREAD-SAFT,是指那個3RD的物件可以在2個(含)以上的THREAD同時被『直接』操作(這邊指的『直接』是指你可以設定一個值到某個屬性,例如:Obj->Active = true; ),不是指在該物件所產生的事件中,你可以『直接』操作其他物件...因為該事件,可能是其他THREAD,不是MAINTHREAD(你是否可確定,該事件是否在MAIN THREAD之中?),而且你是在該事件之中操作『其他』的物件喔....這不一樣喔 照版主大大所說的~~你的問題,是在RUN 9~12天之後才會出問題,是吧? 根據偶個人的經驗,如果一個程式可以持續RUN個3、5天,基本上程式本身,應該就沒問題了(應該啦~~當然這中間,程式要一直都是在忙碌的情況,不是在等待的情況) 說實在的,偶反而比較懷疑是M$的OS的問題ㄝ,建議版主大大用一個乾淨的WIN 2000環境(除了必須的程式不灌其他的軟體),測試一下 最後提一個,治標的方案....版主大大參考一下 你可以利用排程的方式,每天定時重新啟動程式(方法粉簡單,當程式一起動時,先去找找看程式是否已被啟動,如果有,先把原來的程式關掉,再啟動自己,這樣可確保系統中只有一個程式,正在執行),這樣應該會好一點... 如果還重新啟動程式不行,就重新開機吧~~只是重新開機之後,要記得啟動程式(一樣可用排程達到) 參考看看吧 ========================= <>大家一起快樂寫程式
pwipwi
版主


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

發送簡訊給我
#16 引用回覆 回覆 發表時間:2004-08-23 14:33:07 IP:163.28.xxx.xxx 未訂閱
其實Synchronize本身是沒什麼問題, 只是我對他不熟.... 不能確切知道他和主
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#17 引用回覆 回覆 發表時間:2004-08-24 10:12:59 IP:211.76.xxx.xxx 訂閱
老實說,對於 Synchronize() 我也是不熟,只是看到大部分用 TThread 的在叫用事件時都會使用,我也就跟著用。當然,我也試過不用,但在事件中我使用了 VCL 就會當,所以不得不用。    簡單說好了,大家可以參考一下此元件(含 Source、說明文件 可免費使用): http://www.hellix.com/Products/TThreadedTimer.asp 其中,OnTimer 事件可以由使用者自行使用,在此 OnTimer 事件中,使用者可能操作各式 VCL (含 non-Thread-Safe 元件),所以作者使用了 Synchronize(OwnerTimer->Timer) 叫用 OnTimer 事件。    我的問題就是,如何不使用 Synchronize 來叫用事件(不是變數共用的問題),又能讓使用者任意使用 VCL (含 non-Thread-Safe 元件)。如果這是可以作到的,是要如何作到,這樣我才能確認我所使用的 3rd party 元件廠商所說的是對的,不然,到目前為止,我都還是認為那廠商是在唬爛我  < href="http://www.ViewMove.com" target="blank">視動科技 VMASK - ViewMove Automation Software Kernel 發表人 - dllee 於 2004/08/24 10:19:21
------
http://www.ViewMove.com
lu
高階會員


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

發送簡訊給我
#18 引用回覆 回覆 發表時間:2004-08-30 15:44:15 IP:221.169.xxx.xxx 未訂閱
引言: 我的問題就是,如何不使用 Synchronize 來叫用事件(不是變數共用的問題),又能讓使用者任意使用 VCL (含 non-Thread-Safe 元件)。如果這是可以作到的,是要如何作到,這樣我才能確認我所使用的 3rd party 元件廠商所說的是對的,不然,到目前為止,我都還是認為那廠商是在唬爛我
簡單說,用TThrea::Synchronize 基本上是程式的執行權切回主執行緒(Main Thread),執行某一段程式,執行完成後跳回該TThread 您問是不是有其他方式,做到在其他的TTHREAD之中產生一個事件,然後在此一事件是否可以自由的操作所有的VCL,是吧? 如果是這樣,偶的理解是,有粉多方法將程式切回主執行緒,來執行某一段程式喔,例如:之前講過的PostMessage or SendMessage or PostThreadMessage 等方式來實現將程式切回主執行緒的動作。至於那個3RD的廠商所提供的物件,那個物件所引發的事件(EVENT)是否一定是MAIN THREAD,那就要看廠商的說明嘍,偶建議你自己先確定一次,那個物件所引發的事件,是不是都是在MAIN THREAD之下引發的,(檢驗方式粉簡單,在進入該事件後將程式停下來,然後按CTRL + ALT + T觀看THREAD的視窗,你就可以確定,是不是在MAIN THREAD了) ========================= 大家一起快樂寫程式
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#19 引用回覆 回覆 發表時間:2004-08-30 20:30:14 IP:211.76.xxx.xxx 訂閱
引言:偶建議你自己先確定一次,那個物件所引發的事件,是不是都是在MAIN THREAD之下引發的,(檢驗方式粉簡單,在進入該事件後將程式停下來,然後按CTRL + ALT + T觀看THREAD的視窗,你就可以確定,是不是在MAIN THREAD了)
感謝 lu 一語驚醒夢中人 < href="http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55289" target="blank">StatPlus2 視動科技 VMASK - ViewMove Automation Software Kernel
------
http://www.ViewMove.com
bugmans
高階會員


發表:95
回覆:322
積分:188
註冊:2003-04-12

發送簡訊給我
#20 引用回覆 回覆 發表時間:2007-10-10 12:47:45 IP:125.224.xxx.xxx 未訂閱
ATFileNotification http://atorg.net.ru/delphi/atfilenotification.htm
這個元件可以監控檔案和目錄的變化,但我感興趣的是作者宣稱這元件是thread-safe
我閱讀原始碼後發現作者不使用Synchronize而是改用CriticalSetion

[code delphi]
procedure TATFileNotification.Start;
begin
try
EnterCriticalSection(FLock);
if (not FStarted) then
begin
FDirThread := TDirThread.Create(...);
FStarted := True;
end;
finally
LeaveCriticalSection(FLock);
end;

procedure TATFileNotification.Stop;
begin
try
EnterCriticalSection(FLock);
if FStarted then
begin
if Assigned(FDirThread) then
begin
FDirThread.Free;
FDirThread := nil;
end;
FStarted := False;
end;
finally
LeaveCriticalSection(FLock);
end;

procedure TDirThread.Execute;
...
if (...) then
begin
prTimer.Enabled := True;
end;
...

[/code]

然後在TDirThread執行緒內使用VCL元件了,不知道這樣的寫法能不能達到dllee的要求
編輯記錄
bugmans 重新編輯於 2007-10-10 12:50:57, 註解 無‧
bugmans 重新編輯於 2007-10-10 12:51:48, 註解 無‧
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#21 引用回覆 回覆 發表時間:2007-11-13 08:59:16 IP:220.134.xxx.xxx 訂閱
感謝 bugmans 的回覆 ^_^
對不起,因最近較忙,現在才回覆您。

關於您提到的 CriticalSection,是可以防止多個執行緒搶用同一個資源,
但若在
CriticalSection 內使叫用 UI 的 VCL 元件,應該還是不算 Thread-Safe 的。
您提的元件我還沒去下載回來看,不過,我想,它應該是只用到檔案 IO,沒有
UI 元件,那算是 OK 的。

以我個人來說,常常忘記之前問過問題網友們給的答覆,所以每次寫到相關程式
時,還是會回來搜尋自己的問題,再寫程式。如果有相關的資料,可以繼續回覆,
讓訊息更完整,也讓大家都能寫出穩定的好程式。

VMASK - ViewMove Automation Software KernelVMIO-Server/SECS/GEMdllee's blogdllee's StatPlus

------
http://www.ViewMove.com
powerhowardchen
初階會員


發表:15
回覆:28
積分:28
註冊:2004-04-19

發送簡訊給我
#22 引用回覆 回覆 發表時間:2008-06-10 23:55:03 IP:118.165.xxx.xxx 訂閱
各位大大, 太久沒來這了, 現在突然看到這篇才想到一些想法, 很不好意思.
我主要是在 Delphi 上玩, 很少玩BCB, 不過, 我記得原理應該是一模一樣...

事實上, Synchronize 的程式內就是用 CriticalSection 來進行同步的.
Synchronize 的目的是將所有提出同步請求的 Thread 與 MainThread 的行程對齊.

而我認為標示為 ThreadSafe 的 VCL 應該要有幾項特徵.
1.VCL 的本身(含property, method)都是在 MainThread 內建造, 並且由 MainThread 釋放
2.於 MainThread 內的任意條件下存取該 VCL 元件都不會造成資源存取衝突的問題

基於以上的定義, 就是說, 若是我要建造一個符合 ThreadSafe 的 MultiThread VCL,
則我應該要另外建造一堆 非 MainThread 的 Class 供該 VCL 引用,
且自行處理 VCL 內資料同步的問題.

例如, 我若是要做一個 File Change Detect VCL , 則我會寫一個 TFileChangeDetect 的 VCL,
然後寫個"檔案監視器"的 MultiThread VCL 名為 TCheckFileThread,
然後在 TCheckFileThread 用 Synchronize 呼叫 MainThread 同步, 以觸發 Event.

麻煩的是, Synchronize 只對 MainThread 有效, 對其他的Thread是無效的.
若是有各 Thread 的同步需求, 卻又不是 MainThread, 雖然也是可以使用 Synchronize,
但是卻是要把所有相關的 Thread 都叫出來等, 實在是不符經濟效益.

這是我自己研究的小小心得啦...
請參看我回覆的 http://delphi.ktop.com.tw/board.php?cid=30&fid=68&tid=51222
http://delphi.ktop.com.tw/board.php?cid=168&fid=913&tid=52377 兩篇

dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#23 引用回覆 回覆 發表時間:2008-06-11 00:13:40 IP:60.248.xxx.xxx 訂閱
------
http://www.ViewMove.com
系統時間:2024-04-25 13:54:01
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!