2011-04-19 25 views
5

में नहीं बुलाया कॉलबैक GET अनुरोध पर मैं (जैसे कुछ) चलाते हैं। मैं देख सकता हूं कि onComplete एक Index से एक अलग थ्रेड पर लागू किया गया था।WebClient async ASP.NET MVC

प्रश्न: ऐसा क्यों हो रहा है? WebClient का async थ्रेड स्पष्ट रूप से अवरुद्ध क्यों है जब तक कि अनुरोध हैंडलिंग थ्रेड समाप्त नहीं हो जाता है?

ThreadPool से नए धागे को शुरू किए बिना इसे ठीक करने का कोई तरीका है (मैंने कोशिश की है, और थ्रेड पूल का उपयोग करने की अपेक्षा की जाती है। इसके अलावा वेब क्लाइंट का कॉलबैक अपेक्षित होता है यदि डाउनलोडस्ट्रिंगएसिंक को थ्रेडपूल के धागे से बुलाया जाता है)।

ASP.NET MVC 3.0, .NET 4.0, एमएस कैसिनी देव वेब सर्वर (वी.एस. 2010)

संपादित करें: यहाँ एक पूर्ण कोड है:

public class HomeController : Controller { 
    private static ManualResetEvent done; 

    public ActionResult Index() { 
     return Content(DownloadString() ? "success" : "failure"); 
    } 

    private static bool DownloadString() { 
     try { 
      done = new ManualResetEvent(false); 
      var wc = new WebClient(); 
      wc.DownloadStringCompleted += (sender, args) => { 
       // this breakpoint is not hit until after Index() returns. 
       // It is weird though, because response isn't returned to the client (browser) until this callback finishes. 
       // Note: This thread is different from one Index() was running on. 
       done.Set(); 
      }; 

      var uri = new Uri(@"http://us.battle.net/wow/en/character/blackrock/hunt/simple"); 

      wc.DownloadStringAsync(uri); 

      var timedout = !done.WaitOne(3000); 
      if (timedout) { 
       wc.CancelAsync(); 
       // if this would be .WaitOne() instead then deadlock occurs. 
       var timedout2 = !done.WaitOne(3000); 
       Console.WriteLine(timedout2); 
       return !timedout2; 
      } 
      return true; 
     } 
     catch (Exception ex) { 
      Console.WriteLine(ex.Message); 
     } 
     return false; 
    } 
} 

उत्तर

5

मैं इस बारे में उत्सुक था तो मैं माइक्रोसॉफ्ट आंतरिक ASP.NET चर्चा उर्फ ​​पर कहा, और लेवी ब्रॉडरिक से यह जवाब मिला:

ASP.NET आंतरिक तुल्यकालन के लिए SynchronizationContext का उपयोग करता है, और केवल एक थ्रेड को एक समय में उस लॉक के नियंत्रण की अनुमति है। आपके विशेष उदाहरण में, थ्रेड होमकंट्रोलर :: डाउनलोडस्ट्रिंग लॉक रखता है, लेकिन यह मैन्युअल रीसेट इवेंट को निकाल दिया जा रहा है। ManualResetEvent तक रन निकाल दिया नहीं किया जाएगा DownloadStringCompleted विधि है, लेकिन यह विधि एक अलग धागा कि कभी तुल्यकालन ताला नहीं ले सकते क्योंकि पहले धागा अभी भी यह मानती है पर चलता है। आप अब deadlocked हैं।

मुझे आश्चर्य है कि यह कभी भी एमवीसी 2 में काम करता है, लेकिन अगर ऐसा होता है तो यह केवल खुश दुर्घटनाग्रस्त था। यह कभी भी समर्थित नहीं था।

1

इस का उपयोग करने की बात है असीमित प्रक्रिया। आपका मुख्य धागा कॉल शुरू करता है, फिर अन्य उपयोगी चीजें करने के लिए चला जाता है। जब कॉल पूरा हो जाता है, तो यह आईओ पूर्णता थ्रेड पूल से धागा उठाता है और उस पर आपकी पंजीकृत कॉलबैक विधि को कॉल करता है (इस मामले में आपकी पूर्ण विधि)। इस तरह आपको एक लंबे समय तक चलने वाले वेब कॉल को पूरा करने के लिए चारों ओर एक महंगा धागा इंतजार करने की आवश्यकता नहीं है।

वैसे भी, आप जिस विधियों का उपयोग कर रहे हैं वह ईवेंट-आधारित असिंक्रोनस पैटर्न का पालन करें। आप इसके बारे में यहां और अधिक पढ़ सकते हैं: http://msdn.microsoft.com/en-us/library/wewwczdw.aspx

(संपादित करें) नोट: इस उत्तर को अस्वीकार करें क्योंकि यह स्पष्ट प्रश्न का उत्तर देने में मदद नहीं करता है। इसके तहत हुई चर्चा के लिए इसे छोड़कर।

+0

जो बताता है कि। तो, WebClient ThreadPool का उपयोग नहीं करता है? WebClient अनुरोध को कतार कैसे देता है? मैंने इसे थोड़ी देर के लिए परावर्तक के साथ waded लेकिन यह नहीं मिला कि यह कहां होता है। –

+0

यह एक अनुरोध कतार नहीं है। यह वास्तव में तब अनुरोध शुरू करता है। लेकिन अनुरोध शुरू करने के बाद DownloadStringAsync() वापस आ जाएगा और डाउनलोड होने पर आपको अन्य चीजें करने देता है। डाउनलोड के दौरान, वास्तव में कोई धागा मौजूद नहीं है! पूरा होने के बारे में सूचित करने के लिए यह केवल थ्रेडपूल से बाहर धागा खींचता है। – RandomEngy

+0

मैं देखता हूं। तो कोड में कॉलबैक कहां लगाया जाता है? मैंने इंडेक्स से लौटने से पहले थ्रेड स्लीप (10000) डालने की कोशिश की, लेकिन इंडेक्स रिटर्न के बाद भी कॉलबैक को तब तक नहीं बुलाया जाता है। मतलब है कि इंडेक्स कॉल के बाद कॉलबैक कॉल कतारबद्ध हो जाता है। मैं उत्सुक हूं कि ऐसा कैसे होता है। यदि सीएलआर थ्रेडपूल पर कॉलबैक कहा जाता है तो इसे जीईटी अनुरोध प्रसंस्करण धागे द्वारा अवरुद्ध नहीं किया जाना चाहिए, है ना? –

0

चयनित उत्तर के अलावा, वेबक्लिंट सिंक्रनाइज़ेशन कॉन्टेक्स्ट को कैप्चर करने के तरीके के बारे में अधिक जानकारी के लिए इस आलेख को देखें।

http://msdn.microsoft.com/en-gb/magazine/gg598924.aspx