मेरे पास यह वस्तु है:

public class ImageQueueMgr
{
    public delegate void OnImageQueueFilledHandler(int imageQueueId);
    public event OnImageQueueFilledHandler OnImageQueueFilled;

    ReleaseImageQueue(Object obj);

    Delegate[] delegateList;
}

अन्य ऑब्जेक्ट इस ऑब्जेक्ट इवेंट OnImageQueueFilled की सदस्यता ले सकते हैं। मैं चाहता हूं कि सभी वस्तुओं की सदस्यता बनी रहे, लेकिन मैं उन ग्राहकों पर भी नज़र रखना चाहता हूं, जिन्हें ReleaseImageQueue(Object obj) कहा जाता है, ताकि सभी ग्राहकों के कॉल करने के बाद मैं कुछ सफाई कर सकूं:
ReleaseImageQueue(this)

जानने के लिए मेरे पास इस तरह के ग्राहकों की सूची हो सकती है:

delegateList = OnImageQueueFilled?.GetInvocationList();  

तो मेरा सवाल यह है कि, मैं उस प्रतिनिधि को कैसे ढूंढ सकता हूं जो उस वस्तु से मेल खाता है जिसे ReleaseImageQueue(this) कहा जाता है?

0
Pedro Ferreira 7 पद 2020, 19:24

2 जवाब

सबसे बढ़िया उत्तर

मुझे इसके लिए delegate->Target->Equals का उपयोग करके एक समाधान मिला, यह प्रबंधित सी ++ में है लेकिन सी # समकक्ष बहुत सीधा है:

List<Delegate^>^ m_delegateList = gcnew List<Delegate^>();

void SetDelegateList(cli::array<Delegate^>^ delegateList)
{
    // Convert cli::array to List
    for each (Delegate^ delegate in delegateList)
    {
        m_delegateList->Add(delegate);
    }
}

bool RemoveDelegateFromList(System::Object^ obj)
{
    Delegate^ delegateToRemove = nullptr;

    for each (Delegate^ delegate in m_delegateList)
    {
        if (delegate->Target->Equals(obj))
        {
            delegateToRemove = delegate;
            exit;
        }
    }

    if (delegateToRemove != nullptr)
    {
        m_delegateList->Remove(delegateToRemove);

        Debug::Print("removed delegate");
    }

    // If the list of delegates is empty then all of them are done with this image queue
    if (m_delegateList->Count == 0)
    {
        m_mreWaitDone->Set();
    }

    return false;
}
1
Pedro Ferreira 11 पद 2020, 04:48

अगर मुझे समस्या सही ढंग से मिली तो आप वास्तविक घटना आमंत्रण सूची की एक प्रति से प्रतिनिधि को हटाना चाहते हैं, आप वास्तविक घटना से सदस्यता समाप्त नहीं करना चाहते हैं। इस मामले में, आप केवल Delegate.Combine() विधि के साथ किसी अन्य ईवेंट में आमंत्रण सूची की प्रतिलिपि बना सकते हैं। निम्नलिखित कोड पर विचार करें:

 public class ImageQueueMgr
{
    public delegate void OnImageQueueFilledHandler(int imageQueueId);
    public event OnImageQueueFilledHandler OnImageQueueFilled;

    private OnImageQueueFilledHandler _onImageQueueFilledCopy;
    private void CopyEventInvocationList()
    {
        var delegateList = OnImageQueueFilled.GetInvocationList();
        _onImageQueueFilledCopy = (OnImageQueueFilledHandler)Delegate.Combine(delegateList);
    }

    public void NotifyFinish(OnImageQueueFilledHandler finishedHandler)
    {
        _onImageQueueFilledCopy -= finishedHandler;
    }

}

इस तरह ग्राहक वास्तव में सदस्यता समाप्त किए बिना आमंत्रण सूची से प्रतिनिधियों को आसानी से हटा सकते हैं। निम्नलिखित उपयोग उदाहरण देखें:

    public static class Program
    {
        private static ImageQueueMgr _queueManager = new ImageQueueMgr();
        
        public static void ImageQueuedEventProcessor(int imageQueueId)
        {
            //some code here
            //........
            
            //unsubscribe when done
            _queueManager.NotifyFinish(ImageQueuedEventProcessor);
        }
        
        public static void ImageQueuedEventProcessor2(int imageQueueId)
        {
            //some code here
            //........
            
            //unsubscribe when done
            _queueManager.NotifyFinish(ImageQueuedEventProcessor2);
        }

        public static void Main()
        {
            _queueManager.OnImageQueueFilled += ImageQueuedEventProcessor;
            _queueManager.OnImageQueueFilled += ImageQueuedEventProcessor2;
        }
    }
1
Giorgi Chkhikvadze 7 पद 2020, 21:04