2013-02-11 36 views
6

हमारे पास एक लाइब्रेरी है जिसका उपयोग WPF और/या Winforms क्लाइंट द्वारा किया जा रहा है।एसिंक पर डेडलॉक से परहेज करें और यूआई को उत्तरदायी होने से रोकें

int GetInt(); 

जो अनिवार्य रूप से बस अतुल्यकालिक विधि और कॉल कॉल:

Task<int> GetIntAsync() 

हम यह भी (दुर्भाग्य से) एक तुल्यकालिक आवरण विधि प्रदान की है:

हम एक अतुल्यकालिक विधि के समान प्रदान की है अपने काम पर .Result

हमने हाल ही में कुछ परिस्थितियों में महसूस किया है GetIntAsync में कुछ कोड मुख्य यूआई थ्रेड पर चलाने की जरूरत है (इसे एक विरासत COM घटक का उपयोग करने की आवश्यकता है जिसे "एकल" थ्रेडिंग मॉडल के रूप में चिह्नित किया गया है (यानी घटक मुख्य में चलाना चाहिए एसटीए धागा नहीं बस किसी भी एसटीए धागा)

तो समस्या यह है कि GetInt(), यह होगा गतिरोध

के बाद से
  • .Result ब्लॉक मुख्य थ्रेड, मुख्य थ्रेड पर कहा जाता है जब
  • GetIntAsync() के भीतर कोड मुख्य धागे पर चलाने के प्रयास के लिए Dispatcher.Invoke का उपयोग करता है।

सिंक्रोनस विधि पहले से ही उपभोग की जा रही है, इसलिए इसे हटाने के लिए यह एक तोड़ने वाला परिवर्तन होगा। तो इसके बजाय, हमने मुख्य सिग्नल पर काम करने की अनुमति देने के लिए हमारे सिंक्रोनस GetInt() विधि में WaitWithPumping का उपयोग करने का विकल्प चुना है।

यह उन यूआई कोडों से GetInt() का उपयोग करने वाले ग्राहकों को छोड़कर ठीक काम करता है। पहले, उन्होंने उम्मीद की थी कि GetInt() का उपयोग करके उनके यूआई को उत्तरदायी छोड़ दिया जाएगा - यानी, यदि वे बटन के क्लिक इवेंट हैंडलर से GetInt() कहलाते हैं, तो वे उम्मीद करेंगे कि हैंडलर लौटने तक कोई विंडोज संदेश संसाधित नहीं किया गया था। अब उन संदेशों को पंप किया गया है, उनके यूआई उत्तरदायी हैं और उसी बटन को फिर से क्लिक किया जा सकता है (और संभवतः वे अपने हैंडलर को पुन: प्रवेश करने के लिए कोड नहीं देते थे)।

  • क्या कोई:

    अगर वहाँ एक उचित समाधान है, हम अपने ग्राहकों के लिए नहीं करना चाहते हैं GetInt

    प्रश्न कॉल के दौरान उत्तरदायी होने यूआई के खिलाफ कोड करने के लिए की जरूरत है WaitWithPumping करने का तरीका जो "मुख्य पर आमंत्रित करें" संदेशों को पंप करेगा, लेकिन अन्य UI संबंधित संदेशों को पंप नहीं करेगा?

  • यह हमारे उद्देश्यों के लिए पर्याप्त होगा यदि क्लाइंट यूआई व्यवहार करता है जैसे कि एक मॉडल संवाद वर्तमान में दिखाया गया था, हालांकि छुपा हुआ है (यानी उपयोगकर्ता अन्य विंडो तक नहीं पहुंच सका)। लेकिन, जो मैंने पढ़ा है, उससे आप एक मोडल संवाद छुपा नहीं सकते हैं।
  • अन्य कामकाज जिनके बारे में आप सोच सकते हैं उनकी सराहना की जाएगी।

उत्तर

4

मौजूदा संदेश पंप का उपयोग करने के बजाय आप GetInt के संदर्भ में अपना स्वयं का संदेश पंप बना सकते हैं। Here एक ब्लॉग एंट्री है जो एक लिखने के बारे में चर्चा करता है। This is the full solution the blog creates

का उपयोग करके आप लिख सकते हैं कि के रूप में:

public int GetInt() 
{ 
    return AsyncPump.Run(() => GetIntAsync()); 
} 

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

+0

धन्यवाद। मुझे यूआई ब्लॉक दिखाई देता है। असुरक्षित रूप से मुख्य धागे तक पहुंचने का प्रयास मुख्य थ्रेड के लिए मुख्य थ्रेड के डिस्पैचर 'डिस्पैचर। इन्वोक' का उपयोग कर रहा है। मैं इस काम को बनाने का अनुमान लगा रहा हूं, मुझे मुख्य थ्रेड के डिस्पैचर की बजाय सिंक्रनाइज़ेशन कॉन्टेक्स्ट का उपयोग करने के लिए उस कोड को बदलने की आवश्यकता होगी। क्या यह मुख्य धागे के डिस्पैचर के साथ काम करने का कोई तरीका है? –

+0

@MattSmith आपका कोड विशेष रूप से काम नहीं कर रहा है क्योंकि आप मुख्य थ्रेड के प्रेषक का उपयोग कर रहे हैं। – Servy

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

  • कोई संबंधित समस्या नहीं^_^