2009-02-10 16 views
14

में जोड़ा जाने पर किसी ईवेंट को ट्रिगर करना, जब भी किसी ऑब्जेक्ट को Queue<Delegate> में जोड़ा जाता है तो मुझे किसी ईवेंट को ट्रिगर करने में सक्षम होना चाहिए।सी #: किसी ऑब्जेक्ट को कतार

मैं एक नया वर्ग है कि Queue फैली बनाया:

public delegate void ChangedEventHandler(object sender, EventArgs e); 

public class QueueWithChange<Delegate> : Queue<Delegate> 
{ 
    public event ChangedEventHandler Changed; 

    protected virtual void OnChanged(EventArgs e) { 
     if (Changed != null) 
     { 
      Changed(this, e); 
     } 
    } 
} 

और फिर, इस तरह के तरह अन्य वर्ग से घटना संलग्न:

QueueWithChange<TimerDelegate> eventQueue = new QueueWithChange<TimerDelegate>(); 

// 

eventQueue.Changed += new ChangedEventHandler(delegate(object s, EventArgs ex) { 
    //This event is not being triggered, so this code is unreachable atm...and that is my problem 

    if (eventQueue.Count > 0) 
    { 
     eventQueue.Dequeue().Invoke(new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(5) }); 
     actionTimer.Stop(); 
    } 
}); 

लेकिन जब भी मैं एक वस्तु enqueue (eventQueue.Enqueue(something)), संलग्न घटना को निकाल दिया नहीं जा रहा है।

मुझे यहां क्या याद आ रही है?

उत्तर

25

आप गैर सामान्य Queue वर्ग मतलब है, तो आप सिर्फ Enqueue ओवरराइड कर सकते हैं:

public override void Enqueue(object obj) 
{ 
    base.Enqueue(obj); 
    OnChanged(EventArgs.Empty); 
} 

हालांकि, अगर आप सामान्य Queue<T> वर्ग मतलब है, तो ध्यान दें कि ओवरराइड करने के लिए कोई उपयुक्त आभासी विधि। आप अपनी खुद की कक्षा के साथ बेहतर करने के लिए Encapsulate कतार कर सकता:

(** महत्वपूर्ण संपादित करें: हटा आधार स्तरीय !!! **)

class Foo<T> 
{ 
    private readonly Queue<T> queue = new Queue<T>(); 
    public event EventHandler Changed; 
    protected virtual void OnChanged() 
    { 
     if (Changed != null) Changed(this, EventArgs.Empty); 
    } 
    public virtual void Enqueue(T item) 
    { 
     queue.Enqueue(item); 
     OnChanged(); 
    } 
    public int Count { get { return queue.Count; } } 

    public virtual T Dequeue() 
    { 
     T item = queue.Dequeue(); 
     OnChanged(); 
     return item;   
    } 
} 

हालांकि, अपने कोड को देखकर यह, ऐसा लगता है कि आप यहां कई धागे का उपयोग कर रहे हैं। यदि ऐसा है, तो इसके बजाय threaded queue पर विचार करें।

+0

उत्कृष्ट; यही वह है जिसकी तलाश में मैं हूं। गुणवत्ता के जवाब के लिए धन्यवाद मार्क। और मैं आपके द्वारा उल्लिखित थ्रेडेड कतार के बारे में भी जांच करूंगा। –

+0

ध्यान दें कि मैंने गलत तरीके से बेस-क्लास सेट किया है; कोड में तय ... –

+0

एक डिजाइन सिद्धांत परिप्रेक्ष्य से विरासत (व्यापक रूप से बोलने) पर संरचना का उपयोग करना बेहतर है, इसलिए मैं आपके समाधान का समर्थन करता हूं। – uriDium

0

ऑनचेंग को कॉल करने के लिए आपको एनक्यू को ओवरराइड करना होगा।

+0

एनक्यू सामान्य कतार

+0

पर वर्चुअल नहीं है, यह शर्म की बात है। मुझे लगता है कि आपको एक IQueue इंटरफ़ेस बनाना होगा और फिर अपना स्वयं का कार्यान्वयन करना होगा। –

1

कोशिश

public new void Enqueue(Delegate d) 
{ 
    base.Enqueue(d); 
    OnChanged(EventArgs.Empty); 
} 
+0

फिर से घोषित/विधि-छिपाना भंगुर, गैर-बहुलक, और भंगुर है; कॉलर बस अपने कोड को एक कलाकार के साथ छोड़ सकता है। –

3

मैं सिर्फ मैं क्या एक TriggeredQueue फोन पर लिखना था। यह मार्क ग्रेवल द्वारा जवाब प्रेरित है।

आप मेरी पोस्ट यहाँ पा सकते हैं: http://joesauve.com/triggeredqueuet

और यहाँ सार: http://gist.github.com/jsauve/b2e8496172fdabd370c4

यह चार घटनाओं है:

  • WillEnqueue
  • WillDequeue
  • DidEnqueue
  • DidDequeue

तुम इतनी तरह इन में से किसी में हुक कर सकते हैं:

YourQueue.WillEnqueue += (sender, e) => { 
    // kick off some process 
}; 
YourQueue.DidEnqueue += (sender, e) => { 
    // kick off some process 
    // e.Item provides access to the enqueued item, if you like 
}; 
YourQueue.WillDequeue += (sender, e) => { 
    // kick off some process 
}; 
YourQueue.DidDequeue += (sender, e) => { 
    // kick off some process 
    // e.Item provides access to the dequeued item, if you like 
}; 

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

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