2010-08-10 16 views
23

मैं डेल्फी में थ्रेडिंग के इस सामान के साथ नया हूं। इसलिए, मैं एक साधारण क्वेरी अनुप्रयोग बनाने की कोशिश कर रहा हूं जो डेटाबेस के लिए थोड़ा कॉल करता है और थोड़ा समय लेता है, इसलिए मैं उपयोगकर्ता को सतर्क करना चाहता हूं कि पृष्ठभूमि प्रक्रिया है और उसे धीरज रखना है।सरल थ्रेड नमूना डेल्फी

मैंने कई नमूनों की कोशिश की, लेकिन उनमें से कोई भी मेरे लिए काम नहीं करता है, कृपया, क्या कोई मुझे एक साधारण नमूना दिखा सकता है जो काम कर सकता है?

मैं जानता हूँ कि मैं बनाएं साथ TThread की एक प्रकार की घोषणा करना और निष्पादित ओवरराइड ... आदि है .. लेकिन यह है कि जब से मैं हार रहा हूँ ...

डेल्फी 7 का उपयोग करना, SQL सर्वर 2005 और ADO, विंडोज एक्सपी एसपी 3.-

धन्यवाद।) के लिए निष्पादित (

TMyWorkerThread = class(TThread) 
end; 

तो फिर तुम एक समारोह ओवरराइड जोड़ें::

+5

आपने कई नमूने की कोशिश की और आप असफल रहे। तो आपको एक और उदाहरण क्या देगा? आपको अधिक विस्तृत प्रश्न पूछना चाहिए। आपको किस समस्या का सामना करना पड़ रहा है? बीटीडब्लू, यह ट्यूटोरियल अच्छा दिखता है: http://wiki.lazarus.freepascal.org/Multithreaded_Application_Tutorial – adf88

+1

और एक और, कभी-कभी यह बेहतर समाधान होता है (क्योंकि यह आसान है) एप्लिकेशन को कॉल करने के लिए। प्रोसेस मैसेज समय-समय पर आपके समय लेने वाली प्रक्रिया के अंदर (उदाहरण के लिए बस कुछ प्रगति पट्टी को अपडेट करने या कुछ अन्य एनीमेशन खेलने के लिए जो उपयोगकर्ता को दिखा रहा है कि एप्लिकेशन व्यस्त है)। – adf88

+0

HI, adf88, मैं पूरी तरह से आपसे सहमत हूं। लेकिन नमूने के साथ समस्या यह है कि मैं वास्तव में थ्रेड के बारे में पूरी बात नहीं करता हूं, इसलिए मैंने सोचा कि एक साधारण नमूना मेरे लिए चीजों को और स्पष्ट कर सकता है। किसी भी तरह से, मैंने एप्लिकेशन के साथ समस्या हल की। ​​प्रोसेसमेसेस, धन्यवाद –

उत्तर

28

आप धागे के वेब पर कई उदाहरण पा सकते हैं। एकमात्र विशेष विशेषता, यदि आप थ्रेड के अंदर एडीओ कनेक्शन का उपयोग कर रहे हैं, तो यह है कि आप एक ही कनेक्शन साझा नहीं कर सकते हैं।
प्रत्येक थ्रेड को अपना कनेक्शन बनाना होगा, अन्यथा वे बराबर हैं (किसी अन्य थ्रेड के समान नियमों का पालन करना चाहिए।

TADOSQLThread = class(TThread) 
    private 
    FADOQ: TADOQuery; // Internal query 
    FSQL: string;  // SQL To execute 
    FID: integer;  // Internal ID 

    public 
    constructor Create(CreateSuspended:Boolean; AConnString:String; 
         ASQL:string; IDThread:integer); 
    destructor Destroy; override; 
    procedure Execute(); override; 

    property ID:integer read FID write FID; 
    property SQL:string read FSQL write FSQL; 
    property ADOQ:TADOQuery read FADOQ write FADOQ; 
    end; 

बनाएं निर्माता overrided जाता है, और इस तरह दिखेगा:

constructor TADOSQLThread.Create(CreateSuspended:Boolean; AConnString:String; 
           ASQL:string; IDThread:integer); 
begin 

    inherited Create(CreateSuspended); 

    // ini 
    Self.FreeOnTerminate := False; 

    // Create the Query 
    FADOQ := TAdoquery.Create(nil); 
    // assign connections 
    FADOQ.ConnectionString := AConnString; 
    FADOQ.SQL.Add(ASQL); 
    Self.FID := IDThread; 
    Self.FSQL:= ASQL; 
end; 

और निष्पादित विधि बहुत सरल है:

)

एक नमूना है कि मैं का इस्तेमाल किया है यह वह जगह है

procedure TADOSQLThread.Execute(); 
begin 

    inherited; 

    try 
    // Ejecutar la consulta 
    Self.FADOQ.Open; 
    except 
    // Error al ejecutar 
    ...Error treattement 
    end; 
end; 

धागा शुरू करने और बनाने के लिए आप इस तरह के कोड का उपयोग कर सकते हैं:

//crear el Thread 
    th := TADOSQLThread.Create(True, mmConnection.Lines.Text, ASQL, AId); 
    // internal for me (for controled the number of active threads and limete it) 
    inc(numThreads); 
    // evento finalizacion 
    th.OnTerminate := TerminateThread; 
    // Ejecutarlo 
    th.Resume; 

मैं एक TerminateThread विधि है कि धागे का नियंत्रण प्राप्त जब वे खत्म बनाने की है। अन्य धागे के लिए केवल अलग कनेक्शन समस्या है। आपको प्रत्येक थ्रेड पर एक नया कनेक्शन बनाना होगा, यह अन्य एडीकॉन्क्शन को दूसरों के साथ साझा नहीं कर सकता है।
मुझे आशा है कि यह उदाहरण आपके लिए उपयोगी होगा।

सम्मान

46

हाँ, आप एक नए प्रकार जो TThread से विरासत घोषित

TMyWorkerThread = class(TThread) 
public 
    procedure Execute; override; 
end; 

यही प्रक्रिया कॉल किया जाएगा प्रारंभ करने पर अपना धागा। इसे आपके मुख्य कार्यक्रम के साथ समानांतर में निष्पादित किया जाएगा। चलो इसे लिखो।

procedure TMyWorkerThread.Execute; 
begin 
    //Here we do work 
    DoSomeWork(); 
    DoMoreWork(); 
    //When we exit the procedure, the thread ends. 
    //So we don't exit until we're done. 
end; 

इसका उपयोग कैसे करें? आइए मान लें कि जब आप बटन क्लिक करते हैं तो आप काम करना शुरू करना चाहते हैं। आप ऑनक्लिक हैंडलर लिखते हैं:

procedure TMainForm.Button1Click(Sender: TObject); 
begin 
    TMyWorkerThread.Create(false); 
end; 

यही है। उपयोगकर्ता क्लिक बटन के बाद, आपका थ्रेड शुरू होता है और जो कुछ भी आपने किया है, उसे निष्पादित करने के साथ प्राप्त होता है। यदि उपयोगकर्ता दोबारा बटन क्लिक करता है, तो दूसरा धागा शुरू होगा, और फिर दूसरा - प्रत्येक क्लिक पर। वे सभी समानांतर में भाग लेंगे, प्रत्येक निष्पादन() में और जो समाप्त होता है, सब कुछ कर रहा है।

मान लें कि आप यह जांचना चाहते हैं कि काम खत्म हो गया है या नहीं। के लिए, आप कहीं अपने धागा के संदर्भ में स्टोर करने के लिए होगा:

TMainForm = class(TForm) 
{...skipped...} 
public 
    MyWorkerThread: TThread; 
end; 

procedure TMainForm.Button1Click(Sender: TObject); 
begin 
    //This time we make sure only one thread can be started. 
    //If one thread have been started already, we don't start another. 
    if MyWorkerThread<>nil then 
    raise Exception.Create('One thread have already been started!'); 
    MyWorkerThread := TMyWorkerThread.Create(false); 
end; 

procedure TMainForm.Button2Click(Sender: TObject); 
begin 
    //If the work is not over yet, we display message informing the user we're still working 
    if (MyWorkerThread<>nil) and (WaitForSingleObject(MyWorkerThread.Handle, 0)<>WAIT_OBJECT_0) then 
    MessageBox(Self.Handle, pchar("The work is not yet done!"), pchar("Still running"), MB_OK); 
end; 

जैसा कि आप देख, हम जाँच कर रहे हैं अगर एक धागा अभी भी एक Windows समारोह WaitForSingleObject बुलाया फोन करके चल रहा है। यह फ़ंक्शन तब तक प्रतीक्षा करता है जब तक थ्रेड काम नहीं कर लेता है, या टाइमआउट समाप्त हो जाता है, और जैसा कि हम 0 का टाइमआउट निर्दिष्ट करते हैं, तो थ्रेड अभी खत्म नहीं होने पर यह तुरंत मौजूद है।

+2

मुझे यह सिर्फ उदाहरण कोड पता है, लेकिन एक टिप्पणी बताती है कि क्या होता है यदि उपयोगकर्ता एक से अधिक बार बटन क्लिक करता है तो उपयोगी होगा। –

+0

क्या नवीनतम कोड ब्लॉक परिभाषा में "TThread" नहीं होना चाहिए "MyWorkerThread: TMyWorkerThread" इसके बजाय? –

+0

@ThatMarc: यहां विचार यह था कि आपको यह जानने की आवश्यकता नहीं है कि क्या विशेष काम TMyWorkerThread को पता है कि धागा खत्म हो गया है। किसी भी टीटीएचड वंश को इस तरह चेक किया जा सकता है। – himself

संबंधित मुद्दे