2011-01-19 16 views
9

यह कुछ हद तक this question से संबंधित है, लेकिन मुझे लगता है कि मुझे थोड़ा और जानने की आवश्यकता है। मैं अपने सिर को कुछ दिनों के लिए कैसे करना है (अन्य हिस्सों पर काम करते समय) के बारे में अपने सिर को पाने की कोशिश कर रहा हूं, लेकिन मेरे लिए बुलेट काटने और बहु-थ्रेड प्राप्त करने का समय आ गया है। साथ ही, मैं जुड़े प्रश्न से थोड़ा अधिक जानकारी के बाद हूं।boost :: asio, threads और सिंक्रनाइज़ेशन

सबसे पहले, बहु-थ्रेडिंग के बारे में। जैसा कि मैं अपने कोड का परीक्षण कर रहा हूं, मैंने किसी भी बहु-थ्रेडिंग से परेशान नहीं किया है। यह सिर्फ एक कंसोल एप्लिकेशन है जो एक परीक्षण सर्वर से कनेक्शन शुरू करता है और बाकी सब कुछ तब संभाला जाता है।

while(true) 
{ 
    Root::instance().performIO(); // calls io_service::runOne(); 
} 

जब मैं अपने मुख्य आवेदन लिखते हैं, मैं इस समाधान अनुमान लगा रहा हूँ स्वीकार्य नहीं होगा (के रूप में यह संदेश पाश में कहा जा करने के लिए होता है जो, जबकि संभव हो, के लिए होता है: मुख्य पाश यह है संदेश संदेश कतार ब्लॉक संदेश के लिए इंतजार कर रहा है। आप इसे बदल सकते हैं ताकि संदेश-लूप ब्लॉक न हो, लेकिन फिर यह छत के माध्यम से सीपीयू उपयोग को फटकारने वाला नहीं है?)

इसका समाधान ऐसा लगता है कि इसमें एक और धागा फेंकना है। अच्छा ठीक है। लेकिन फिर मैंने पढ़ा है कि io_service::run() ऐसा करने के लिए कोई काम नहीं करता है। वो क्या है? क्या ऐसा कोई डेटा नहीं है, या कोई कनेक्शन नहीं है? यदि कम से कम एक कनेक्शन मौजूद है तो क्या यह जीवित रहेगा? यदि ऐसा है, तो यह एक समस्या का इतना अधिक नहीं है क्योंकि मुझे पहले कनेक्शन होने पर केवल एक नया धागा शुरू करना होगा और अगर मैं कुछ भी नहीं चल रहा हूं तो यह सब बंद हो जाता है। मुझे लगता है कि मैं 'काम करने के लिए कोई काम नहीं' की परिभाषा से उलझन में हूं।

तब मुझे अपने मुख्य जीयूआई थ्रेड के साथ अपने बूस्ट थ्रेड को सिंक्रनाइज़ करने के बारे में चिंता करने की ज़रूरत है। तो, मुझे लगता है कि मेरे प्रश्न हैं:

  1. थ्रेड के संबंध में क्लाइंट एप्लिकेशन में बूस्ट :: एएसओ का उपयोग करने और उन्हें जीवित रखने का सबसे अच्छा तरीका क्या है?
  2. मुख्य धागे से आईओ थ्रेड तक सॉकेट लिखते समय, boost::asio::post का उपयोग करके सिंक्रनाइज़ेशन प्राप्त किया जाता है, ताकि कॉल बाद में io_service में हो?
  3. जब डेटा प्राप्त होता है, तो लोग यूआई थ्रेड पर डेटा कैसे प्राप्त करते हैं? अतीत में जब मैंने पूरा बंदरगाहों का उपयोग किया, तो मैंने एक विशेष कार्यक्रम बनाया जो डेटा को वापस भेजकर मुख्य UI थ्रेड पर :: SendMessage का उपयोग कर पोस्ट कर सकता था। यह सुरुचिपूर्ण नहीं था, लेकिन यह काम किया।

मैं आज और कुछ पढ़ रहा हूं, लेकिन यह पहले से ही ऐसा करने वाले किसी व्यक्ति से सिर प्राप्त करना बहुत अच्छा होगा। बूस्ट :: एएसओ दस्तावेज बहुत अच्छा नहीं है, और अब तक मेरा अधिकांश काम दस्तावेज, कुछ परीक्षण/त्रुटि, वेब पर कुछ उदाहरण कोड पर आधारित है।

उत्तर

6

1) io_service::work पर एक नज़र डालें। जब तक एक कार्य वस्तु मौजूद है io_service :: रन वापस नहीं आएगा। तो यदि आप अपना साफ-सफाई करना शुरू करते हैं, तो कार्य ऑब्जेक्ट को नष्ट करें, किसी भी उत्कृष्ट परिचालन को रद्द करें, उदाहरण के लिए सॉकेट पर async_read, वापस लौटने के लिए प्रतीक्षा करें और अपने संसाधनों को साफ़ करें।

2) io_service :: पोस्ट io_service चलाने वाले थ्रेड से दिए गए हैंडलर को असीमित रूप से निष्पादित करेगा। ऑपरेशन के परिणाम प्राप्त करने के लिए कॉलबैक का उपयोग किया जा सकता है।

3) आपको नए डेटा के अपने जीयूआई थ्रेड को सूचित करने के लिए मैसेजिंग सिस्टम के कुछ रूपों की आवश्यकता है। यहां कई संभावनाएं हैं।

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

+0

+1 io_service :: काम यह है कि मैं इस समस्या को स्वयं कैसे हल करता हूं। आपकी प्रतिक्रिया के लिए –

+0

धन्यवाद। जब आप कहते हैं कि कई संभावनाएं हैं, तो आपने पहले क्या उपयोग किया है? –

+0

@ म्यू-रस, मैं ऐसी स्थिति में नहीं रहा हूं जहां एक विशिष्ट जीयूआई थ्रेड था जिसे डेटा को संभालने के लिए आवश्यक था। मैंने अभी कॉलबैक तंत्र का उपयोग किया है और डेटा को आईओ_एस सर्विस थ्रेड से संभाला है जैसा कि आया था।संदेश कतार के कुछ रूप जो गुई धागे पढ़ते हैं, का उपयोग नए डेटा के आगमन को इंगित करने के लिए किया जा सकता है। या आप बस एक सशर्त चर का उपयोग कर सकते हैं। रेली आपके आवेदन, डिजाइन और आवश्यकताओं पर निर्भर करता है। सलाह के लिए –

1

boost::io_service::run() केवल तभी वापस आएगा जब ऐसा करने के लिए कुछ भी नहीं है, इसलिए कोई एसिंक ऑपरेशन लंबित नहीं है, उदा। async स्वीकार/कनेक्शन, async पढ़ने/लिखने या async टाइमर प्रतीक्षा करें। इसलिए io_service::run() पर कॉल करने से पहले आपको पहले एसिंक ऑप शुरू करना होगा।

मुझे आपके पास कंसोल या जीयूआई ऐप नहीं मिला है? किसी भी मामले में मल्टीथ्रेडिंग एक ओवरकिल की तरह दिखता है। आप अपने संदेश पाश के साथ संयोजन के रूप में Asio का उपयोग कर सकते हैं। अगर यह Win32 GUI है तो आप OnIdle() हैंडलर से io_service :: run_one() को कॉल कर सकते हैं। कंसोल एप्लिकेशन के मामले में आप deadline_timer सेट कर सकते हैं जो नियमित रूप से उपयोगकर्ता इनपुट के लिए (प्रत्येक 200ms?) जांचता है और io_service::run() के साथ इसका उपयोग करता है। एकल थ्रेड में सब कुछ बहुत समाधान

2

1) धागे के संबंध में एक क्लाइंट अनुप्रयोग में बढ़ावा का उपयोग कर :: asio और उन्हें जीवित रखने का सबसे अच्छा अभ्यास तरीका क्या है सरल करने के लिए?

documentation suggests के रूप में, धागे io_service::run लागू की एक पूल सबसे स्केलेबल और आसान लागू करने के लिए है।

2) जब आईओ धागा करने के लिए मुख्य धागे से एक सॉकेट के लिए लिख, तुल्यकालन, बढ़ावा :: asio :: पद का प्रयोग कर प्राप्त किया जाता है ताकि कॉल io_service में बाद में क्या होता है?

आपको किसी भी हैंडलर की रक्षा के लिए a strand का उपयोग करने की आवश्यकता होगी जिसे एकाधिक धागे द्वारा बुलाया जा सकता है। this answer देखें क्योंकि यह आपकी सहायता कर सकता है, साथ ही साथ यह उदाहरण भी।

3) जब डेटा प्राप्त होता है, तो लोग डेटा को यूआई थ्रेड पर वापस कैसे प्राप्त करते हैं? में जब मैंने पूरा बंदरगाहों का उपयोग किया, मैंने एक विशेष घटना बनाई जो को मुख्य UI थ्रेड पर वापस भेज सकता है :: SendMessage का उपयोग कर। यह सुरुचिपूर्ण नहीं था, लेकिन यह काम किया।

कैसे जब आप io_service को एक अतुल्यकालिक घटना के बाद एक boost::function के रूप में एक कॉलबैक उपलब्ध कराने के बारे में? फिर ईवेंट का हैंडलर कॉलबैक का आह्वान कर सकता है और परिणामों के साथ यूआई अपडेट कर सकता है।

+0

इस जानकारी के लिए धन्यवाद। मुद्दा यह था कि मेरे कॉलबैक को थ्रेड से बुलाया जा रहा है जो 'io_service :: run' कहता है, जो मुख्य UI थ्रेड नहीं है। मुझे लगता है कि मैं प्रॉक्सी प्रतिनिधि होने के द्वारा इसे हल करूँगा जो यूआई थ्रेड पर किसी अन्य प्रतिनिधि को आमंत्रित करने के लिए SendMessage का उपयोग करता है। तारों के लिए, मैंने उन्हें इस्तेमाल किया है। हालांकि, मैंने 'io_service :: पोस्ट (strand_.wrap (' स्ट्रैंड :: पोस्ट' की बजाय 'का उपयोग किया है, क्या यह गलत है? –

+0

@ म्यू-रस यह उस संदर्भ पर निर्भर करता है जहां उनका उपयोग किया जाता है, पोस्ट और रैप दोनों समान होते हैं –

+0

अच्छी तरह से, मैं सॉकेट स्तर पर ** पोस्ट ** का उपयोग करता हूं, उदाहरण के लिए, जब मैं डेटा को सार्वजनिक इंटरफ़ेस पोस्ट को आंतरिक रूप से भेजता हूं जो 'async_write_some' शुरू करता है। एक उच्च-अप अबास्ट्रक्शन (वह कतार आदेश प्रेषित किया जाता है) उपयोग ** रैप ** इसके तरीकों पर न केवल इसे किसी भी थ्रेड से पोस्ट किया जा सकता है, लेकिन यह अपने स्वयं के समय सीमा टाइमर सेट करता है (कतार को बहुत तेजी से भेजा जा रहा है)। –

0

जब डेटा प्राप्त होता है, तो लोग यूआई थ्रेड पर डेटा कैसे प्राप्त करते हैं? अतीत में जब मैंने पूरा बंदरगाहों का उपयोग किया, तो मैंने एक विशेष कार्यक्रम बनाया जो डेटा को वापस भेजकर मुख्य UI थ्रेड पर :: SendMessage का उपयोग कर पोस्ट कर सकता था। यह सुरुचिपूर्ण नहीं था, लेकिन यह

:: पोस्टमेसेज अधिक उपयुक्त हो सकता है।

जब तक कि सब कुछ एक धागे में नहीं चलता है, इन तंत्रों को यूआई थ्रेड में सुरक्षित रूप से ईवेंट पोस्ट करने के लिए उपयोग किया जाना चाहिए।

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