2009-03-05 13 views
6

के साथ बेनामी प्रतिनिधि का उपयोग करना मैं एक प्रश्न पोस्ट करने जा रहा था, लेकिन इसे समय से पहले समझ लिया और प्रश्न और उत्तर - या कम से कम मेरे अवलोकन पोस्ट करने का फैसला किया।.NET ThreadPool.QueueUserWorkItem

WaitCallback, जहां ThreadPool.QueueUserWorkItem एक foreach पाश में कहा जाता है के रूप में एक गुमनाम प्रतिनिधि का उपयोग करते समय, यह प्रतीत होता है कि एक ही एक foreach-मूल्य प्रत्येक थ्रेड में पारित कर दिया गया है।

List<Thing> things = MyDb.GetTheThings(); 
foreach(Thing t in Things) 
{ 
    localLogger.DebugFormat("About to queue thing [{0}].", t.Id); 
    ThreadPool.QueueUserWorkItem(
     delegate() 
     { 
      try 
      { 
       WorkWithOneThing(t); 
      } 
      finally 
      { 
       Cleanup(); 
       localLogger.DebugFormat("Thing [{0}] has been queued and run by the delegate.", t.Id); 
      } 
     } 
} 
मैंने देखा कि प्रत्येक 'थिंग' WorkWithOneThing के लिए पारित 'बातें' की सूची में अंतिम आइटम के अनुरूप था हालात में 16 बात उदाहरणों का एक संग्रह के लिए

मुझे संदेह है क्योंकि प्रतिनिधि 'टी' बाहरी चर का उपयोग कर रहा है। ध्यान दें कि मैंने अज्ञात प्रतिनिधि को पैरामीटर के रूप में थिंग को पास करने के साथ भी प्रयोग किया था, लेकिन व्यवहार गलत रहा।

जब मैंने नामित वेटकॉलबैक विधि का उपयोग करने के लिए कोड को फिर से पहचाना और विधि में थिंग 'टी' पास किया, तो व्हायोला ... चीजों का उदाहरण वर्कविथऑनटिंग में सही ढंग से पारित किया गया था।

समांतरता में एक सबक मुझे लगता है। मैं यह भी सोचता हूं कि समांतर। परिवार के लिए यह पता चलता है, लेकिन इस बिंदु पर वह पुस्तकालय हमारे लिए एक विकल्प नहीं था।

आशा है कि यह किसी और को कुछ समय बचाएगा।

हावर्ड हॉफमैन

+0

आप इस कोड को संकलित करने के लिए प्रयास करते हैं, तो आपको एक त्रुटि "System.Threading.WaitCallback 0 'तर्क' नहीं ले करता है '' के रूप में आप कोई परम – ram

+0

राम निर्दिष्ट नहीं मिलेगा से ऊपर घोषणा: प्रतिनिधि() { ... } प्रतिनिधि को { ... } है यही कारण है कि मैं क्या था मेरे परिवर्तन को आगे बढ़ाने के लिए। उम्मीद है कि यह आपकी मदद करता है। –

उत्तर

7

यह सही है, और बताता है कि कैसे सी # बंद अंदर बाहर चर कैप्चर करता है। यह समानांतरता के बारे में सीधे एक मुद्दा नहीं है, बल्कि अज्ञात विधियों और लैम्ब्डा अभिव्यक्तियों के बारे में है।

This question इस भाषा सुविधा और इसके प्रभावों को विस्तार से चर्चा करता है।

+0

यह आलेख भी सहायक था: http://www.managed-world.com/archive/2008/06/13/lambdas---now-your-closures.aspx –

1

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