2010-02-12 17 views
11

हमारे पास यह आम परिदृश्य है जहां हमारे पास एक ऐसी विधि है जो कुछ क्रियाओं को असीम तरीके से करती है और जब यह हो जाती है तो एक ईवेंट उठाता है।क्या एसिंक्रोनस विधि सिंक्रनाइज़ करने का एक सामान्य तरीका है?

ManualResetEvent reset = new ManualResetEvent(false); 
someobject.AsyncActionDone += (sender, args) => reset.Set(); 
someobject.PerformAsyncAction(); 
reset.WaitOne(); 

वहाँ एक तरीका यह है एक सहायक विधि लिखने के लिए है:

बार जहाँ हम चाहते हैं कि उसे तुल्यकालिक बजाय तो हम कोड है कि इस के समान दिखता है किया हैं? मैं प्रदर्शन करने के लिए क्रिया में पास कर सकता हूं, लेकिन मुझे यकीन नहीं है कि कुछ ऐसा कैसे किया जाए जिससे सहायक विधि को यह पता चल सके कि कौन सी घटना सुननी है क्योंकि ऐसा नहीं लगता है कि आप एक इवेंट हैंडलर को पैरामीटर के रूप में पास कर सकते हैं।

अधिमानतः एक समाधान है कि प्रतिबिंब की आवश्यकता नहीं है

वहाँ कुछ भ्रम हो रहा है, यह क्या someobject की कक्षा का एक नमूना है की तरह है:

public class SomeClass 
{ 
    private ExternalServer someServerOverTheNetwork = new ExternalServer(); 

    public event EventHandler AsyncActionDone; 
    public Data SomeData { get; set; } 
    public void PerformAsyncAction() 
    { 
     someServerOverTheNetwork.GetSomeData(OnDataRetrived); 
    } 

    public Data OnDataRetrived(Data someData) 
    { 
     AsyncActionDone(this, new DataEventArgs(someData)); 
    } 
} 
+0

क्या आप किसी चीज़ के कार्यान्वयनकर्ता हैं या क्या यह एक पुस्तकालय प्रकार है जिसे संशोधित नहीं किया जा सकता है? –

+0

हम हैं, हालांकि ऐसी कई वस्तुएं हैं। अधिकांश कार्यों में सर्वर से अनुरोध भेजने और परिणाम वापस आने का इंतजार करना शामिल है, इसलिए वे डिफ़ॉल्ट रूप से एसिंक क्यों हैं। – Davy8

+0

हमारे पास सर्वर से ऑब्जेक्ट्स की एक सूची को कैश करने, हमारे सबसे सामान्य कार्यों में से एक के लिए ऐसा करने का एक तरीका है, हालांकि यह सटीक ऑब्जेक्ट प्रकार और सुनने के लिए ईवेंट को जानने पर निर्भर करता है। मैं किस घटना को सुनने में सक्षम होना चाहता हूं ताकि हम डुप्लिकेट कोड को कम कर सकें, क्योंकि केवल उन्हीं चीज़ों को अलग करना है जो पूरा होने पर उठाए गए तरीके और घटना हैं। – Davy8

उत्तर

4

मैं एसिंक्रोनस ऑपरेशन करने वाली वस्तुओं में Asynchronous Design Pattern को लागू करने पर विचार करता हूं।

public object Operation(object arg) 
{ 
    var ar = BeginOperation(arg, null, null); 

    return EndOperation(ar); 
} 

public IAsyncResult BeginOperation(object arg, AsyncCallback asyncCallback, object state) 
{ 
    AsyncResult asyncResult = new AsyncResult(asyncCallback, state); 

    // Lauch the asynchronous operation 

    return asyncResult; 
} 

private void LaunchOperation(AsyncResult asyncResult) 
{ 
    // Do something asynchronously and call OnOperationFinished when finished 
} 

private void OnOperationFinished(AsyncResult asyncResult, object result) 
{ 
    asyncResult.Complete(result); 
} 


public object EndOperation(IAsyncResult asyncResult) 
{ 
    AsyncResult ar = (AsyncResult)asyncResult; 

    return ar.EndInvoke(); 
} 

इस पैटर्न के साथ आपके ऑब्जेक्ट पर एकाधिक समवर्ती असीमित ऑपरेशन होने की लचीलापन है।

नोट: आप आसानी से वेब पर एक सामान्य AsyncResult कक्षा का कार्यान्वयन पा सकते हैं।

संपादित करें:

आप वर्तमान डिजाइन रखने के लिए, यदि आपके सभी वस्तु केवल एक अतुल्यकालिक आपरेशन हो सकता है चाहता हूँ के रूप में, तो आप एक IAsyncOperation इंटरफेस को परिभाषित करने और अपने सभी वस्तु में इसे लागू कर सकते हैं।

public interface IAsyncOperation 
{ 
    event EventHandler AsyncActionDone; 
    void PerformAsyncAction(); 
} 

तो फिर तुम हो सकता है:

public static CallSynchronously(IAsyncOperation asyncOperation) 
{ 
    ManualResetEvent reset = new ManualResetEvent(false); 
    asyncOperation.AsyncActionDone += (sender, args) => reset.Set(); 
    asyncOperation.PerformAsyncAction(); 
    reset.WaitOne(); 
} 

अपने वस्तुओं कई अतुल्यकालिक आपरेशन शामिल कर सकते हैं, तो प्रतिबिंब के बिना मुझे लगता है कि प्राप्त करने के लिए आप क्या करना चाहते हैं कोई रास्ता नहीं है, लेकिन आप अभी भी निर्धारित कर सकते हैं मैन्युअल रीसेट इवेंट को लपेटने वाले सभी एसिंक्रोनस ऑपरेशन का एक सिंक्रोनस संस्करण।

public void PerformAction() 
{ 
    ManualResetEvent reset = new ManualResetEvent(false); 
    this.AsyncActionDone += (sender, args) => reset.Set(); 
    this.PerformAsyncAction(); 
    reset.WaitOne(); 
} 
+0

मैं ऐसे समाधान के लिए शूटिंग कर रहा हूं जिसमें 'someobject' की श्रेणी को संशोधित करने में शामिल नहीं है वर्तमान पैटर्न पहले से ही हमारे सिस्टम में दर्जनों कक्षाओं में मौजूद है। – Davy8

+0

उम्मीदवार के साथ एक बेहतर व्याख्या के साथ संपादित प्रश्न – Davy8

+0

उत्तर को भी संपादित किया गया –

3

अगर मैं अपने बहाव को पकड़ने, आप कर सकते हैं बस निम्नलिखित तरीके से प्रतिनिधियों का उपयोग करें, एक प्रतिनिधि बनाने आप कॉल से काम के लिए, चलो यह

public delegate string AsyncDelegate(); 

तो कहते हैं, एक प्रॉक्सी funct बनाने इस तरह आयन:

public static void ExecuteSync(AsyncDelegate func) 
    { 
     ManualResetEvent reset = new ManualResetEvent(false); 
     int threadId; 
     func.BeginInvoke((a)=>reset.Set(), null); 
     reset.WaitOne(); 
    } 

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

का आनंद लें!

+0

यदि मुझे गलत नहीं लगता है कि मान लीजिए कि आपके पास पहले से ही एक सिंक्रोनस फ़ंक्शन है, है ना? जब मैं 'someobject.PerformAsyncAction() को कॉल करता हूं;' यह कार्रवाई को कतार में आता है और तुरंत लौटता है, मुझे नहीं लगता कि मैंने अपनी विधि में अपना फ़ंक्शन पारित किया है, तो यह पता चलेगा कि कार्रवाई वास्तव में कब की जाती है। – Davy8

+0

जब कार्रवाई पूर्ण होती है, तो वह कॉलबैक को कॉल करता है जो मैन्युअल रीसेट इवेंट 'सेट' करता है। मैन्युअल रीसेट इवेंट 'सेट' होने तक मुख्य फ़ंक्शन वापस नहीं आएगा। – Foole

+0

कार्रवाई पूर्ण होने पर यह कैसे पता चलता है? सभी एक्शन फ़ंक्शन एक संदेश भेजता है और फिर तुरंत लौटाता है। – Davy8

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