dcsimg
Results 1 to 4 of 4

Thread: Event handlers

  1. #1

    Thread Starter
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051

    Event handlers

    I'm using a class defined in an external library that allows access to a generic save device.

    This class has an event handler for when it aquired the device.

    I can then use the device to save/load, providing the device has been aquired.


    I want to write an extension method that will perform a given method on the device if it's been aquired, and if it hasn't it will aquire it then perform the given method.

    A first attempt as below:
    Code:
    public delegate void PostAquireDeviceAction();
    public static void AquireDevicePerformAction(this SaveDevice saveDevice, PostAquireDeviceAction callMethod)
    {
        if (!saveDevice.HasValidStorageDevice)
        {
            saveDevice.PromptForDevice();
    
            saveDevice.DeviceSelected += (sender, eventargs) =>
            {
                callMethod();
            };
        }
        else
        {
            callMethod();
        }
    }
    The issue with this is after calling this method, if the device is aquired again, that method will get called again (since it's a handler for the event).

    How can i get round this issue?
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


  2. #2
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    104,673

    Re: Event handlers

    You could use a second method as the event handler instead. In that event handler, first detach itself as an event handler, then call the desired method.

  3. #3
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Event handlers

    You can't unregister a lambda from an event handler, so you'll have to move that into a separate method, and then unregister the method as part of handling the event.

    However, have you considered whether that is actually what you want to be doing? When your AquireDevicePerformAction method returns, there is no guarantee that the action has actually been performed... It would seem more logical for this method to block until the device has been acquired (if necessary) and then run the action. That way you can guarantee the action has been performed at the end of the method, which is the contract you're implying with the method name.

    Does the API you're using have a blocking version of PromptForDevice? If not, you could use synchronisation primitives (such as a ManualResetEvent) to block until the DeviceSelected event fires.

  4. #4

    Thread Starter
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051

    Re: Event handlers

    Thanks for the replys.

    Giraffe, I'm fine with it only calling the method if we have a valid device. If i find i need to then there are other events i can hook for if the device couldn't be aquired.
    I can't block this thread because this is a game loop and the game loop needs to update in order to get the device (it shows a screen to the player). Possibly i should rename the method to bettwe reflect the intentions though.

    I've taken in both your comments and have tried making the 'methodCaller' a method, as below:
    Code:
    public class MethodCallerEventArgs : EventArgs
    {
        public PostAquireDeviceAction CallMethod;
        public SaveDevice SaveDevice;
    
        public MethodCallerEventArgs(SaveDevice SaveDevice, PostAquireDeviceAction CallMethod)
            : base()
        {
            this.SaveDevice = SaveDevice;
            this.CallMethod = CallMethod;
        }
    }
    
    public static void MethodCaller(object sender, MethodCallerEventArgs EventArgs)
    {
        EventArgs.SaveDevice.DeviceSelected -= MethodCaller;
        EventArgs.CallMethod();
    }
    
    public static void AquireDevicePerformAction(this SaveDevice SaveDevice, PostAquireDeviceAction CallMethod)
    {
        if (!SaveDevice.HasValidStorageDevice)
        {
            SaveDevice.PromptForDevice();
            SaveDevice.DeviceSelected += MethodCaller;
        }
        else
        {
            CallMethod();
        }
    }
    The issue i get now though, is that i've had to create a new eventargs class so i can pass in my method to call and because of that the method can't be used as an event handler for the DeviceSelected event.
    Last edited by SLH; Nov 11th, 2010 at 03:38 AM.
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width