2010-08-16 19 views
8

में सिंक्रोनस कॉल लेना मैं WP7 संस्करण में पूर्ण .NET ढांचे से कुछ कोड पोर्ट कर रहा हूं और मैं सिंक्रोनस बनाम एसिंक कॉल के साथ किसी समस्या में भाग रहा हूं।सिल्वरलाइट WP7

string response; 
string requestString = GenerateReqString(); 
HttpWebRequest req = (HttpWebRequest) WebRequest.Create("endpoint"); 
req.Method = "POST"; 
req.ContentType = "text/xml"; 

req.ContentLength = requestString.Length; 

StreamWriter sw = new StreamWriter (req.GetRequestStream(), System.Text.Encoding.ASCII); 
sw.Write(requestString); 
sw.Close(); 

StreamReader sr = new StreamReader(req.GetResponse().GetResponseStream()); 
response = sr.ReadToEnd(); 
sr.Close(); 

प्रतिक्रिया स्ट्रिंग को तब विधि द्वारा लौटाई गई वस्तुओं की एक सूची में पार्स किया जाता है।

मेरी समस्या यह है कि सिल्वरलाइट/WP7 में कॉल को सिंक्रनाइज़ करने का कोई तरीका नहीं है। अगर मैं कॉल बैक का उपयोग करता हूं तो मुझे एक अलग फ़ंक्शन में प्रतिक्रिया मिल जाएगी और इसे मूल फ़ंक्शन से वापस करने में सक्षम नहीं होगा। क्या कॉल को सिंक्रनाइज़ करने या कॉलबैक फ़ंक्शन से वापस आने के तरीके को एसिंक कॉल से लात मारने का कोई तरीका है?

उत्तर

11

आपको समस्या के बारे में अलग-अलग सोचने की आवश्यकता है। एसिंक्रोनस चीजें सिंक्रोनस को "महसूस" करने के लिए, इसे करने का सबसे आसान तरीका है 'continuation passing style' का उपयोग करने के लिए अपने कोड को पुन: व्यवस्थित करना।

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

void DoSomethingAsync(Action<string> callback) { 
    HttpWebRequest req; // TODO: build your request 

    req.BeginGetResponse(result => { 
     // This anonymous function is a closure and has access 
     // to the containing (or enclosing) function. 
     var response = req.EndGetResponse(result); 

     // Get the result string and call the callback 
     string resultString = null; // TODO: read from the stream 

     callback(resultString); 
    }, null); 
} 

यह एक आधा समाधान है:

यहाँ एक उदाहरण है, जो गुमनाम कार्यों और lambdas का उपयोग करता है। अगला भाग, वास्तव में इसे कॉल करना है। कल्पना करें कि आपके पास आईसीओएमएंड इंस्टेंस या सरल है, बटन पर क्लिक करें जो इस फ़ंक्शन को कॉल करने और "स्ट्रिंग प्राप्त करने" के लिए आवश्यक है। "स्ट्रिंग प्राप्त करने" के बजाय आप इस फ़ंक्शन को कॉल करते हैं और कॉलबैक विधि प्रदान करते हैं (जो बंद हो जाएगा)। http://blogs.msdn.com/b/wesdyer/archive/2007/12/22/continuation-passing-style.aspx

+0

आइए कहें ProcessWebResponseResult() स्ट्रिंग से एक ऑब्जेक्ट बनाता है और फ़ंक्शन जो DoSomethingAsync() को उस ऑब्जेक्ट को वापस करने की आवश्यकता है। क्या यह संभव है? – CACuzcatlan

+0

उस बिंदु को याद कर रहा है। DoSomethingAsync को कॉल करने वाली विधि DoSomethingAsync को फ़ंक्शन पास करती है। पारित समारोह "इस कार्य के परिणाम के साथ क्या करना है"। जैसा कि आपको और चाहिए, आप अपनी कॉल श्रृंखला में अतिरिक्त निरंतरता फ़ंक्शन जोड़ते हैं। –

+0

इस तरह आप सामान्य रूप से चल रहे कार्यक्रम के बारे में सोचते हैं: 'ए(); बी(); सी(); '। हालांकि, जब आप 'निरंतरता गुजरने वाली शैली' के साथ निष्पादित करते हैं, तो आप प्रत्येक कार्य को बताते हैं कि यह कब किया जाता है। "मुझे इस फ़ंक्शन से मेरा परिणाम मिल गया" के बजाय, आप कहते हैं, "मैं इस कार्य को बताता हूं कि इसके परिणाम के साथ क्या करना है" एक प्रतिनिधि के माध्यम से। –

1

चेक बाहर Wintellect पावर थ्रेडिंग पुस्तकालय है, जो आप एक तुल्यकालिक प्रोग्रामिंग मॉडल के साथ अतुल्यकालिक कार्रवाई करने की अनुमति देता है:

void btnGo_Click(object sender, EventArgs e) { 
    DoSomethingAsync(resultString => { 
     // This anonymous function is called when the web request has 
     // finished and has your string. 

     // Now that we have the string, we can go and process it. 
     ProcessWebResponseResult(resultString); 
    }); 
} 

यहाँ एक बहुत अच्छी अवधारणा समझाने लेख है।

http://csharperimage.jeremylikness.com/2010/03/sequential-asynchronous-workflows-in.html

2

सबसे पहले मैं async के साथ सहज होने की कोशिश करने का सुझाव लेकिन अगर आप वास्तव में चाहते हैं/एक अतुल्यकालिक कॉल एक तुल्यकालिक को आप ManualResetEvent उपयोग कर सकते हैं वांछित परिणाम प्राप्त करने में परिवर्तित करने की जरूरत है।

public ManualResetEvent _event = new ManualResetEvent(false); 

... 
{ 
    ... 
    var wc = new WebClient(); 
    wc.OpenReadCompleted += new OpenReadCompletedEventHandler(ReadCompleted); 
    wc.OpenReadAsync(uri); 

    // block until async call is complete 
    _event.WaitOne(); 
} 

private static void ReadCompleted(object sender, OpenReadCompletedEventArgs e) 
{ 
    ... 
    // set event to unblock caller 
    _event.Set(); 
} 

अब आप कोड _event.Set(); जब तक लाइन _event.WaitOne(); पर अवरुद्ध कर देगा कहा जाता है:

यहां एक त्वरित उदाहरण है अगर उपयोग है।

शुभकामनाएं!

-2

यह असीमित रूप से ऐसा करना बेहतर है ताकि उपयोगकर्ता डिवाइस से बातचीत कर सके।

मुझे संदेह है कि आप ऐसा करना चाहते हैं कि उपयोगकर्ता आपके अनुरोध पूरा होने तक कुछ नियंत्रणों के साथ बातचीत करने से रोकने के लिए है।

इस तक पहुंचने का स्वीकार्य तरीका यूआई तत्वों को छिपाने या अक्षम करना है जिन्हें अनुरोध प्रसंस्करण के दौरान बातचीत नहीं की जानी चाहिए।

+0

यह सब बेहतर है कि इसे दूर करने के लिए बेहतर है और शुरू करने के लिए उच्च स्तर पर इसे असंकालिक रूप से करना शुरू कर दिया है, जिस बिंदु पर, आप अपने निम्न स्तर के अनुरोध को सिंक्रनाइज़ करना चाहते हैं क्योंकि आप पहले से ही किसी प्रकार के कार्यकर्ता थ्रेड पर हैं। –