2011-01-21 12 views
9

क्या प्रत्येक डब्ल्यूसीएफ सेवा कॉल Async बनाने का कोई कारण है?क्या प्रत्येक डब्ल्यूसीएफ कॉल असिनक बनाने का कोई कारण है?

मैं अपने साथी के साथ यह चर्चा कर रहा था। वह UI को लॉक करने से बचने के लिए प्रत्येक WPF सेवा कॉल Async बनाना चाहता है (यह एक डेस्कटॉप WPF एप्लिकेशन है)। मैं इस विचार के खिलाफ हूं। मुझे लगता है कि ज्यादातर मामलों में एसिंक कॉल की आवश्यकता नहीं है, और जब इसकी आवश्यकता होती है तो अनुरोधिंग क्लास और डेटामैनेजर को विशेष रूप से Async कॉल को संभालने के लिए कोड किया जाना चाहिए।

इसके लिए मेरे तर्क यह है कि सबकुछ के लिए कॉलबैक सेट अप करने के लिए कहीं अधिक कोड है और यह बहुत भ्रमित है। मुझे यह भी लगता है कि इससे प्रदर्शन में कमी आ सकती है, हालांकि मैंने अभी तक यह सत्यापित नहीं किया है। उनका तर्क यह है कि कभी-कभी आपको बहुत अधिक डेटा मिल रहा है और यह यूआई को लॉक कर देगा, और ऐसा डब्ल्यूसीएफ कॉल सेट करने के लिए इतना काम नहीं है (उसे निम्नलिखित कोड भ्रमित नहीं लगता है)।

हमने दोनों पहले कभी डब्लूसीएफ सर्वर के साथ काम नहीं किया है, इसलिए मैंने सोचा कि मैं उसे संदेह का लाभ दूंगा और कुछ अन्य विचारों के लिए यहां पूछूंगा।

उदाहरण के लिए:

माय वे:

public override User GetById(int id) 
{ 
    return new User(service.GetUserById(id)); 
} 

यह यूआई, UserDataManager, और उपयोगकर्ता DataTransferObject साथ WCF सर्वर रिटर्न जब तक WCF सेवा चैनल ताले, लेकिन यह समझने में आसान है और कोड के लिए जल्दी। इसका उपयोग अधिकांश डब्ल्यूसीएफ सेवा कॉल के लिए किया जाएगा जब तक कि वास्तव में डेटा प्राप्त करने में देरी की उम्मीद न हो, इस स्थिति में डेटामैनेजर Async कॉल को संभालने के लिए सेटअप किया जाएगा।

उनका रास्ता: आधार वर्ग पर

public override void GetById(int id, Action<UserGroup> callback = null) 
{ 
    // This is a queue of all callbacks waiting for a GetById request 
    if (AddToSelectbyIdQueue(id, callback)) 
     return; 

    // Setup Async Call 
    var wrapper = new AsyncPatternWrapper<UserDTO>(
     (cb, asyncState) => server.BeginGetUserById(id, cb, asyncState), 
     Global.Instance.Server.EndGetUserById); 

    // Hookup Callback 
    wrapper.ObserveOnDispatcher().Subscribe(GetByIdCompleted); 

    // Run Async Call 
    wrapper.Invoke(); 
} 

private void GetByIdCompleted(UserDTO dto) 
{ 
    User user = new User(dto); 

    // This goes through the queue of callbacks waiting 
    // for this method to complete and executes them 
    RunSelectIdCallbacks(user.UserId, user); 
} 

कॉलबैक कतार:

/// <summary> 
/// Adds an item to the select queue, or a current fetch if there is one 
/// </summary> 
/// <param name="id">unique object identifier</param> 
/// <param name="callback">callback to run</param> 
/// <returns>False if it needs to be fetched, True if it is already being 
/// fetched</returns> 
protected virtual bool AddToSelectbyIdQueue(int id, Action<T> callback) 
{ 
    // If the id already exists we have a fetch function already going 
    if (_selectIdCallbacks.ContainsKey(id)) 
    { 
     if(callback != null) 
      _selectIdCallbacks[id].Add(callback); 
     return true; 
    } 

    if (callback != null) 
    { 
     List<Action<T>> callbacks = new List<Action<T>> {callback}; 
     _selectIdCallbacks.Add(id, callbacks); 
    } 

    return false; 
} 

/// <summary> 
/// Executes callbacks meant for that object Id and removes them from the queue 
/// </summary> 
/// <param name="id">unique identifier</param> 
/// <param name="data">Data for the callbacks</param> 
protected virtual void RunSelectIdCallbacks(int id, T data) 
{ 
    if (_selectIdCallbacks.ContainsKey(id)) 
    { 
     foreach (Action<T> callback in _selectIdCallbacks[id]) 
      callback(data); 

     _selectIdCallbacks.Remove(id); 
    } 
} 

यह यूआई, DataManager, या WCF सेवा चैनल लॉक नहीं करता है, फिर भी अतिरिक्त की एक बहुत कुछ कोडिंग इसमें जाता है।

AsyncPatternWrapper हमारे आवेदन में परवाह किए बिना है। यह कुछ हमें Async WCF कॉल करने और एक कॉलबैक घटना

संपादित हम एक आवरण है जो हम यूआई धागे से उपयोग कर सकते हैं किसी भी DataManager कॉल रैप करने के लिए है सदस्यता के लिए अनुमति देता है। यह BackgroundWorker पर सिंक्रोनस विधि निष्पादित करता है, और परिणामों के विरुद्ध कॉलबैक निष्पादित करता है।

अतिरिक्त कोड का अधिकांश डेटामैनेजर और डब्ल्यूसीएफ सेवा चैनल को लॉक करना रोकने के लिए है।

+3

नई सी # "async/प्रतीक्षा" सुविधा के सीटीपी रिलीज का मूल्यांकन करने पर विचार करें। यह इस तरह के कोड को लिखने के लिए डिज़ाइन किया गया है। एसिंक फ़ोरम पर आपकी प्रतिक्रिया प्राप्त करने में हमें खुशी होगी। http://msdn.microsoft.com/en-us/vstudio/async.aspx –

+0

@Eric: धन्यवाद, मैं अब इसमें देख रहा हूं और अब तक मुझे यह पसंद है! – Rachel

+0

@Eric: क्या आप मुझे डब्ल्यूसीएफ सेवा के साथ इसका उपयोग करने के बारे में किसी भी अच्छे ट्यूटोरियल/पैदल यात्रा की ओर इशारा कर सकते हैं? – Rachel

उत्तर

6

आपका साथी सही है; आपको यूआई थ्रेड को अवरुद्ध नहीं करना चाहिए।

एसिंक कॉल के विकल्प के रूप में, आप पृष्ठभूमिवर्कर या थ्रेडपूल का उपयोग करके पृष्ठभूमि थ्रेड में सिंक्रोनस कॉल भी कर सकते हैं।

+0

हम वास्तव में एक रैपर करते हैं जो ऐसा करता है ... यह UIM को लॉक करना बंद करने के लिए पृष्ठभूमिवर्कर थ्रेड में DataManager कॉल निष्पादित करता है, हालांकि यूआई थ्रेड से डेटामैनेजर नहीं कहा जाता है (कारण यह है कि WPF ऑब्जेक्ट्स को परिवर्तित नहीं कर सकता पृष्ठभूमिवर्कर से यूआई थ्रेड पर)। मैं डेटामैनेजर और डब्ल्यूसीएफ चैनल को लॉक करना बंद करने के लिए सभी अतिरिक्त कोडिंग के बारे में चिंतित हूं। मैं अपना प्रश्न अपडेट करूंगा। – Rachel

+0

क्या आप अभी भी दूसरी तरफ सिफारिश करेंगे? मुझे इसके साथ कोई समस्या नहीं है अगर यह चीजों को करने का बेहतर तरीका है, लेकिन अगर जरूरत नहीं है तो चीजों को अधिक जटिल नहीं करना चाहते हैं – Rachel

+0

@ राहेल: आपको अभी भी वेब सेवा कॉल के लिए एक अलग थ्रेड का उपयोग करना चाहिए, बस उपयोग करें डिस्पैचर.इनवोक() कॉल रिटर्न करते समय UI को अपडेट करने के लिए - Google के माध्यम से बहुत सारी जानकारी। –

2

कुछ ध्यान देने योग्य बातें:

  1. कोई WCF कॉल संभवतः अपने समय समाप्ति की अवधि तक ब्लॉक कर सकते हैं और आप समय इसे ध्यान में रखना चाहिए। खोए गए कनेक्शन के मामले में यूआई अवरुद्ध होने पर यह खराब उपयोगकर्ता अनुभव के लिए बनाता है।कॉल सामान्य से धीमी गति से भी चला सकते हैं, उदाहरण के लिए, सर्वर को दबा दिया गया है।

  2. भले ही आप एसिंक्रोनस उद्देश्यों के लिए कॉल को लपेट नहीं रहे हैं, तो शायद आप प्रॉक्सी को कॉल के कुछ लपेटना चाहेंगे। ऐसा इसलिए है क्योंकि प्रॉक्सी पर कोई भी कॉल संभावित रूप से चैनल को एक ग़लत स्थिति में डाल सकता है और यदि ऐसा होता है, तो आप चैनल पर abort() को कॉल करने के लिए हैं या आप संसाधनों को रिसाव कर सकते हैं। कुछ अतिरिक्त जानकारी के लिए this post और this other post देखें। डब्ल्यूसीएफ प्रॉक्सी का इस्तेमाल सामान्य कक्षाओं जैसे नहीं किया जा सकता है और यदि आप उन्हें उत्पादन परिदृश्य में उपयोग करना चाहते हैं तो अतिरिक्त रैपिंग को शामिल करना आवश्यक है। यह काफी हद तक अपरिहार्य है, क्योंकि यह अतिरिक्त सीमा मामलों और रिमोट संचार आवश्यकताओं द्वारा पेश किए गए अप्रत्याशित व्यवहार का परिणाम है।

+0

मैंने बहुत सारे कोड को हटा दिया ताकि मैं केवल प्रासंगिक कोड दिखा सकूं। DataManagers में सभी सेवा कॉल कुछ ऐसी चीजों में लिपटे हैं जो अपवाद/दोषों को पकड़ती हैं और यह सुनिश्चित करती हैं कि चैनल खुला रहता है। अधिकांश डेटा प्रबंधक कॉल कुछ ऐसी चीज में लिपटे होते हैं जो उन्हें पृष्ठभूमिवर्कर पर निष्पादित करता है और यूआई अवरुद्ध करता है। हालांकि अच्छी सलाह :) – Rachel

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