2009-12-11 10 views
10

अजीब एक है कि मैं अभी भी नहीं मिलता है भाव, यह है:अपवाद

कहो,

try 
{ 
    stateClient.Socket.BeginSend(messagePrefixed, 0, messagePrefixed.Length, 
     SocketFlags.None, ar => stateClient.Socket.EndSend(ar), stateClient); 
} 
catch (SocketException ex) 
{ 
    // Handle SocketException. 
} 
catch (ObjectDisposedException ex) 
{ 
    // Handle ObjectDisposedException. 
} 

मुझे समझ नहीं आता क्यों लैम्ब्डा अभिव्यक्ति है कि ObjectDisposedException साथ देता पकड़ा नहीं है !? मैं भेड़ के बच्चे में गहराई से जा रहा था और मैं इसे समझ नहीं सकता। क्या यह लैम्ब्डा के दायरे के बारे में है? रेंज वैरिएबल? थ्रेड मुद्दा? मुझे पता है कि लैम्ब्डा के पास उनकी प्रकृति से कोई बहु-थ्रेडिंग नहीं है लेकिन जैसा कि आप देख सकते हैं कि रिटर्न एक और थ्रेड से आता है जो BeginSend द्वारा बनाया गया है। कार्यान्वयन को लैम्ब्डा में बदलने से पहले यह ठीक था जब मेरे पास AsyncCallBack विधि EndSend को संभालने वाली विधि थी।

किसी भी मदद की सराहना की। अग्रिम धन्यवाद।

उत्तर

17

आप सही हैं कि लैमडास में अंतर्निहित एसिंच्रोनिटी या अंतर्निहित मल्टीथ्रेडिंग नहीं है, लेकिन सॉकेट। बेगिनसेन्ड करता है।

क्या होता है कि प्रयास ब्लॉक BeginSend को कॉल को समाहित करता है। यदि वह कॉल सफल हो जाती है, तो कोई अपवाद नहीं फेंक दिया जाता है और संलग्नक विधि वापस आती है, इससे कोई फर्क नहीं पड़ता कि अन्य धागे पर क्या होता है।

यदि BeginSend को कॉल के दौरान कोई अपवाद होता है, तो आपके कैच ब्लॉक लागू किए जाएंगे।

हालांकि, लैम्ब्डा अभिव्यक्ति एक असीमित कॉलबैक है, इसलिए इसे बाद में लागू नहीं किया जा रहा है। यह एक अलग थ्रेड पर एक अलग कॉलस्टैक में होता है, इसलिए कोशिश ब्लॉक वहां प्रभावी नहीं है।

यदि आप कॉलबैक के लिए त्रुटि प्रबंधन चाहते हैं, तो आपको इसे कॉलबैक के अंदर निर्दिष्ट करना होगा (यानी, लैम्ब्डा के अंदर)।

+0

अच्छी तरह से मार्क समझाया गया, धन्यवाद .. –

7

यह लैम्बडा से संबंधित नहीं है। BeginSend के प्रतिनिधि दूसरे थ्रेड पर निष्पादित करते हैं, इसलिए catch कथन वाले अपवाद को अपवाद नहीं किया जाता है और इस प्रकार यह अनचाहे है। EndSend के लिए कोड के साथ अपना अपवाद हैंडलिंग रखें।

अधिक जानकारी के लिए देख http://msdn.microsoft.com/en-us/library/38dxf7kt.aspx

+0

जो कुछ मैं पहले करता हूं, मैं बस सोच रहा था कि मैं इससे बच सकता हूं :) लेकिन पूरी समझ में आता है ... –

+1

यह कहकर कि 'BeginSend' कॉल किसी अन्य थ्रेड पर निष्पादित नहीं है, भ्रामक नहीं है? –

+0

एंजेलो, मैं नहीं जानता कि आपको क्या भ्रामक मतलब है। सभी Beginxxx विधियां एक "प्रारंभ", "कॉल" की तुलना में किसी अन्य धागे पर निष्पादित कर रही हैं, वे विधियां सीपीयू के मल्टी I/O भाग का उपयोग कर रही हैं और स्वचालित रूप से थ्रेडिंग को संभालने में हैं। –

1

गुमनाम समारोह लैम्ब्डा द्वारा परिभाषित करने के लिए कॉल एसिंक्रोनस रूप से होता है। कोशिश ब्लॉक तब तक लंबे समय तक चला जाएगा।

आप कोड एक ही प्रकार है: -

AsyncCallBack cb = delegate(AsyncCallback ar) { stateClient.Socket.EndSend(ar); } 
stateClient.Socket.BeginSend(messagePrefixed, 0, messagePrefixed.Length, 
    SocketFlags.None, cb, stateClient); 

अब आप एक समारोह में परिभाषित किया जा सकता था: -

void MyCallBack(AsyncCallback ar) { stateClient.Socket.EndSend(ar); } 

और फिर ऊपर कोड बन सकता है: -

stateClient.Socket.BeginSend(messagePrefixed, 0, messagePrefixed.Length, 
    SocketFlags.None, MyCallBack, stateClient); 

इस मामले में यह सब कुछ एक ही बात है। मुद्दा यह है कि Try जाल अपवाद जो उसके शरीर के नाममात्र निष्पादन के दौरान होते हैं। तथ्य यह है कि आपने शरीर के अंदर लैम्ब्डा के रूप में परिभाषित कोड को उस कोड को Try ब्लॉक के ऊपर MyCallBack के रूप में नहीं बनाया है। दोनों को उस समारोह के बाद चलाया जाएगा जिसमें Try ब्लॉक या संभवतः एक अलग धागे पर होगा।

+0

वास्तव में मैं लैम्ब्डा के बजाय बेनामी विधि का उपयोग कर सकता हूं, आपके प्रयास के लिए धन्यवाद :) –

0

जैसा कि पहले से ही अन्य उत्तरों में बताया गया है कि लैम्ब्डा को कॉल असीमित रूप से घटित होगा और यही अपवाद नहीं पकड़ा जा रहा है।

अतुल्यकालिक साथ एक उदाहरण एक फ़ाइल से पढ़ने के लिए कॉल:

File.WriteAllText("example.txt", new string('0', 2048)); 

Stream s = File.OpenRead("example.txt"); 

var buffer = new byte[1024]; 

Console.WriteLine(
    "Thread: {0} - Before asynch call...", 
    Thread.CurrentThread.ManagedThreadId); 

s.BeginRead(
    buffer, 
    0, 
    1024, 
    ar => 
    { 
     Thread.Sleep(100); // Simulate a long op 
     Console.WriteLine(
      "Thread: {0} - Callback called...", 
      Thread.CurrentThread.ManagedThreadId); 
    } 
    , 0); 

Console.WriteLine(
    "Thread: {0} - After asynch call...", 
    Thread.CurrentThread.ManagedThreadId); 

// Wait for callback to be executed 
Thread.Sleep(2000); 

उत्पादन होगा:

Thread: 1 - Before asynch call... 
Thread: 1 - After asynch call... 
Thread: 3 - Callback called... 
0

जितना मुझे लगता है कि मैं अभी तक हूँ, BeginSend वापस कभी नहीं होगा एक अपवाद, सभी उत्साह और परिणाम EndSend() विधि पर वापस आ गए हैं, इसलिए यह है कि मैं अपने प्रयास पकड़ ब्लॉक को स्थानांतरित कर सकता हूं।

+0

अगर (सॉकेट === शून्य) तो शुरू करें तो BeginSend आपको एक NullReferenceException देता है –

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