2010-02-21 11 views
7

मैं पृष्ठभूमि थ्रेड में डेटाबेस क्वेरी निष्पादित करना चाहता हूं। OmniThread लाइब्रेरी मुझे सभी थ्रेड सामानों में मदद करेगी, लेकिन एक बात है जो मुझे अब तक समझ में नहीं आ रही है:पृष्ठभूमि थ्रेड में बनाए गए क्वेरी-परिणाम का सही तरीके से उपयोग कैसे करें?

प्रत्येक थ्रेड को एक अलग डेटाबेस कनेक्शन की आवश्यकता होती है। इसलिए पृष्ठभूमि धागा डीबी कनेक्शन बनाता है, क्वेरी बनाता है और फिर इसे निष्पादित करता है।

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

यदि मैं केवल पृष्ठभूमि-थ्रेड क्वेरी ऑब्जेक्ट का संदर्भ देता हूं, तो क्या इससे समस्याएं उत्पन्न होती हैं क्योंकि मैं किसी अन्य थ्रेड में डीबी कनेक्शन तक पहुंच रहा हूं?

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

मेरी सोच विकृत कहां है और ऐसा करने का सही तरीका क्या है?

उत्तर

12

अपने OTL काम है कि कंपनियों मानदंड से मेल खाते की एक हल कर सूची लोड करने की जरूरत है:

// create and open query to fetch list of companies 
while not qryCompanies.Eof do begin 
    C := TCompany.Create; 
    try 
    C.LoadFromDataset(qryCompanies); 
    Companies.Add(C); 
    except 
    C.Free; 
    raise; 
    end; 
    qryCompanies.Next; 
end; 

C एक कंपनी के लिए अपने व्यापार वस्तु है। यह ऑब्जेक्ट द्वारा लागू ऑब्जेक्ट (TCompany) या एक इंटरफेस (ICompany) द्वारा किया जा सकता है। Companies एक TList<TCompany> या TList<ICompany> है। प्रपत्र में

Task.Comm.Send(TOmniMessage.Create(MSGID_LIST_OF_COMPANIES, Companies)); 

जहां कंपनियों की सूची में आपको लगता है कि अपने कार्य की निगरानी कर रहा है otlEventMonitor उदाहरण के OnTaskMessage घटना संभाल प्रदर्शित करना चाहते हैं: काम के अंत में आप VCL धागा करने के लिए कंपनियों की सूची में भेज :

procedure TListBaseFrame.otlEventMonitorTaskMessage(
    const task: IOmniTaskControl); 
var 
    MsgID: word; 
    MsgValue: TOmniValue; 
begin 
    task.Comm.Receive(MsgID, MsgValue); 
    Assert(MsgValue.IsInterface); 
    if fLoaderTask = task then begin 
    SetLoadedData(MsgID, MsgValue.AsInterface); // or MsgValue.AsObject); 
    fLoaderTask := nil; 
    end; 
end; 

कंपनियों की सूची पिछली सूची को प्रतिस्थापित करती है और ग्रिड में प्रदर्शित की जा सकती है।

इसी तरह आप प्रदर्शित और संपादित करने के लिए एक एकल कंपनी ऑब्जेक्ट/इंटरफ़ेस वापस कर सकते हैं।

दो चीजें हैं जो के बारे में सोच के लायक हैं: इंटरफेस के

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

    select * from foo where (...) order by (...) 
    

    को क्रियान्वित करने के बजाय मैं ही कभी अमल एक

    select id, change_index from foo where (...) order by (...) 
    

    तो कैश में जाँच करें कि क्या एक ही आईडी (प्राथमिक कुंजी) और परिवर्तन सूचकांक पहले से मौजूद है, यदि ऐसा है तो कैश्ड वापसी के साथ एक वस्तु ऑब्जेक्ट, और केवल तभी जब कोई नया व्यवसाय ऑब्जेक्ट न बनाएं और सभी कॉलम लोड न करें।

    लेकिन यदि आप वस्तुओं को कैश करते हैं तो आपके पास एकाधिक धागे से संदर्भ होंगे, और स्वामित्व के मुद्दे जल्द ही जटिल हो जाते हैं कि संदर्भ गणनाओं के आधार पर आजीवन प्रबंधन अकेले रहने का एकमात्र तरीका है। वस्तुओं के बजाय इंटरफेस का उपयोग इस संबंध में बहुत मदद करता है।

  • प्रत्येक व्यापार ऑब्जेक्ट में एक सिंक्रनाइज़ेशन ऑब्जेक्ट जोड़ना जरूरी है, यदि एकाधिक थ्रेड एक साथ पहुंच सकते हैं। यह निश्चित रूप से संभव है, लेकिन अतिरिक्त जटिलता और संभावित deadlocks पेश कर सकते हैं। यदि आप अपनी व्यावसायिक वस्तुओं को अपरिवर्तनीय के रूप में लागू करते हैं, तो किसी भी ताले की आवश्यकता नहीं है। मैं उस दृष्टिकोण का अधिक से अधिक उपयोग कर रहा हूं, और जब इसे कुछ उपयोग करने में लग रहा है तो यह चीजों को बहुत सरल बना सकता है।

+0

बिल्कुल सही! यही वही है जो मैं याद कर रहा था ... परिणाम को अन्य धागे पर प्राप्त करने का तरीका। बहुत बहुत धन्यवाद! – Holgerwa

+0

+1 महान जवाब! – jpfollenius

+0

सामान्य उत्तर, सामान्य रूप से! – gabr

5

जीयूआई में डीबी-जागरूक घटकों का उपयोग करने का सबसे अच्छा तरीका शायद सबसे अच्छा तरीका है। थ्रेड को डेटाबेस ऑब्जेक्ट्स के साथ संवाद करना चाहिए और व्यवसाय वस्तुओं में स्टोर जानकारी देना चाहिए, जिसे बाद में मुख्य धागे (जिसे उन्हें प्रदर्शित किया जाएगा) में भेजा जा सकता है।

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

+0

".. और व्यापार वस्तुओं में जानकारी संग्रहीत करें।" यही वह बिंदु है जहां मैं फंस गया हूं। मैं किसी भी डेटा जागरूक घटकों का उपयोग नहीं करता, मुझे केवल मुख्य परिणाम में क्वेरी परिणाम डेटा प्राप्त करने की आवश्यकता है। आप व्यवसाय वस्तु के रूप में क्या संदर्भित करते हैं? – Holgerwa

+1

बिजनेस ऑब्जेक्ट = क्लास का एक उदाहरण जिसमें आपके डेटाबेस से डेटा शामिल है, ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग तरीके में परिवर्तित किया गया है (यानी SQL परिणाम की तरह नहीं दिखता है, लेकिन जब आप अपनी समस्या का अध्ययन करते हैं तो पेपर पर डिज़ाइन करते हैं)। – gabr

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