2011-11-29 14 views
8

मैं उपयोग कर रहा हूं .एएसपेरल()। ForAll() ASP.NET अनुरोध के संदर्भ में समानांतर में संग्रह को गणना करने के लिए। गणना विधि सिस्टम पर निर्भर करती है। थ्रेडिंग। थ्रेड। कंटेंट प्रिंसिपल।क्या PLINQ एक्सटेंशन का उपयोग करते समय थ्रेड पहचान स्थानांतरित हो जाती है?

क्या मैं अपने सिस्टम के लिए उपयोग किए जाने वाले व्यक्तिगत धागे पर भरोसा कर सकता हूं। थ्रेडिंग। थ्रेड। कंटेंट प्रिंसिपल एएसपी.NET अनुरोध को संसाधित करने वाले थ्रेड के HttpContext.Current.User पर सेट है या क्या मुझे इसे प्रबंधित करने की आवश्यकता है?

प्रश्न पूछने का एक और तरीका यह है कि PLINQ द्वारा उपयोग किए गए धागे ऑपरेशन को लागू करने वाले थ्रेड की पहचान प्राप्त करते हैं?

+0

देखें कि बैकिंग फ़ील्ड '[थ्रेडस्टैटिक] है, यदि नहीं, तो आपको ठीक होना चाहिए। – leppie

+0

@joeenzminger यहां एक परीक्षण के लिए http://stackoverflow.com/a/13049286/50776 देखें जो दिखाता है कि PLINQ 'ExecutionContext' (और इसलिए' Thread.CurrentPrincipal') बहता है। – casperOne

उत्तर

11

नहीं, पहचान इन कार्यकर्ता धागे को स्वचालित रूप से प्रचारित नहीं की जाएगी। यदि, वास्तव में, आप जिन घटकों का उपयोग कर रहे हैं वे HttpContext.User हैं जो आप कर सकते हैं वर्तमान "थ्रेड" वर्तमान में "परिवेश" HttpContext उदाहरण को अपने "मुख्य" थ्रेड में कैप्चर करें और इसे अपने कार्यकर्ता धागे में प्रचारित करें। इस तरह यह कुछ दिखेगा:

HttpContext currentHttpContext = HttpContext.Current; 

myWorkItems.AsParallel().ForAll(wi => 
{ 
    HttpContext.Current = currentHttpContext; 

    try 
    { 
     // anything called from here out will find/use the context of your original ASP.NET thread 
    } 
    finally 
    { 
     // Disassociate the context from the worker thread so that it is not held on to beyond its official lifetime 
     HttpContext.Current = null; 
    } 
}); 

यह काम करता है क्योंकि HttpContext.Current स्थिर एक धागा के द्वारा समर्थित है, इसलिए हर कार्यकर्ता धागा अपने मुख्य थ्रेड और किसी भी काम उस बिंदु से उस पर किया है कि देखेंगे से उदाहरण आवंटित किया जाएगा वर्तमान उदाहरण के रूप में।

अब, आपको अवगत होना चाहिए कि HttpContext और इसके संबंधित वर्गों को थ्रेड सुरक्षित होने के लिए डिज़ाइन नहीं किया गया था, इसलिए यह एक हैक है। यदि आप केवल गुणों से पढ़ रहे हैं तो यह वास्तव में एक समस्या नहीं है। यदि आप उन घटकों का उपयोग नहीं कर रहे हैं जो HttpContext.Current पर भरोसा करते हैं तो यह सेट करने के लिए "क्लीनर" होगा और इसके बजाय केवल कार्यकर्ता में कब्जा currentHttpContext चर का उपयोग करें।

Principal logicalPrincipal = Thread.CurrentPrincipal; 

myWorkItems.AsParallel().ForAll(wi => 
{ 
    Principal originalWorkerThreadPrincipal = Thread.CurrentPrincipal; 
    Thread.CurrentPrincipal = logicalPrincipal; 

    try 
    { 
     // anything called from here out will find the principal from your original thread 
    } 
    finally 
    { 
     // Revert to the original identity when work is complete 
     Thread.CurrentPrincipal = originalWorkerThreadPrincipal; 
    } 
}); 
+0

उत्तर के लिए धन्यवाद। मैंने यही सोचा, लेकिन मैंने सोचा कि शायद एक मौका हो सकता है कि कम से कम आपका दूसरा उदाहरण PLINQ नलसाजी में हुड के नीचे हो रहा था। –

+0

ध्यान दें कि 'थ्रेड। कंटेंट प्रिंसिपल' * प्रवाह * करता है, http://stackoverflow.com/a/13049286/50776 देखें जो दिखाता है कि कैसे। – casperOne

3

इस के पीछे CurrentPrincipal

public static IPrincipal CurrentPrincipal 
{ 
    get 
    { 
     lock (CurrentThread) 
     { 
      IPrincipal threadPrincipal = CallContext.Principal; 
      if (threadPrincipal == null) 
      { 
       threadPrincipal = GetDomain().GetThreadPrincipal(); 
       CallContext.Principal = threadPrincipal; 
      } 
      return threadPrincipal; 
     } 
    } 
    set { CallContext.Principal = value; } 
} 

कार्यान्वयन सभी नव निर्मित धागे अशक्त होगा है और यह आवेदन डोमेन से ले जाया जाएगा। तो यह ठीक होना चाहिए। फिर भी आपको संस्कृति से सावधान रहना चाहिए। यह धागा शुरू करने से नहीं लिया जाएगा। देखें: Parallel Programing, PLINQ and Globalization

+1

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

1

एक सूक्ष्म बात है जब प्रधान गुजर नोटिस:

अंत में, यदि सब तुम सच में की जरूरत कार्यकर्ता धागे के लिए वर्तमान प्रिंसिपल प्रचार करने के लिए है, तो आप सिर्फ इतना है कि बजाय एक ही दृष्टिकोण का उपयोग कर सकते हैं के माध्यम से .एस्परेल() सीमा: जहां आपका अनुक्रम भौतिक हो जाता है?

यह .ForAll() के साथ एक समस्या नहीं है, लेकिन एक और परिदृश्य पर विचार करें:

var result = items.AsParallel().Select(MyTransform); 

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

इस मामले में MyTransform लागू हो जाता है, थ्रेड। वर्तमान प्रिंसिपल मूल्य में कुछ अप्रत्याशित हो सकता है।

तो, यहां कामकाज स्पॉट पर क्वेरी को पूरा करने के लिए है (पर कॉल करके।ToArray(), .ToList(), आदि)

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