Am I using the right approach to monitor the tasks I want to perform when a handle is created?

眉间皱痕 提交于 2019-12-01 05:23:24

Greg,

What you have is not an observer pattern, but rather a message queue. So you're just using the wrong design pattern for the problem you're trying to solve.

Its easy enough to implement your own message queue from scratch using a Queue{Action{object}}, where objects enqueue themselves, and you simply dequeue items as you invoke them.

The usual way would be to store a boolean value as to whether it should run...

bool runMyEvent = true;

void Handler(object sender, EventArgs e) {
   if (runMyEvent) {
      // handler here
      runMyEvent = false;
   } else {
      return;
   }
}

You can use the run once method here, mentioned a few times here, but there are a couple problems with that, depending on your use case.

1) You may want to re-hook the method later again, and have it run once again. Though I suppose you can reset your bool

2) You still have that reference which could end up keeping your class in memory instead of being garbage collected.

One option is to use an anonymous method and a closure when you define the event handling:

public class Foo
{
    public EventHandler<EventArgs> MyEvent;

    public void FireEvent()
    {
        if(MyEvent != null)
            MyEvent(this, EventArgs.Empty);
    }
}

Foo obj = new Foo();

Action<object, EventArgs> action = new Action<object, EventArgs>((sender, args) =>
{
    // We're now running the event handler, so unsubscribe
    obj.MyEvent -= new EventHandler<EventArgs>(action);

    // Do whatever you wanted to do when the event fired.
});

obj.MyEvent += new EventHandler<EventArgs>(action);

how about a handler that runs only once? Something like this:


if (wasRun)
    return;
wasRun = true;

Dolphin

If it makes sense (and if you have access to the code that calls the handlers) maybe you could just remove all the events after you run the handler.

I don't know if this is a good idea either, just another thought.

You can use WeakReference objects to introduce so to say weak subscribers. During event firing you can check whether weak reference was already collected or not and remove this subscriber from the list of subscribers if necessary.

The basic idea behind this is that when subscribers are GC collected, your handler will notice it and throw them away from the subscribers list.

There is a thorough article on CodeProject: Weak events, which deals with several solutions to this problem.

I usually do something like the following to implement a 1 time event handler.

void OnControlClickOneTime(this Control c, EventHandler e) {
  EventHandler e2 = null;
  e2 = (s,args) => {
    c.Click -= e2;
    e(s,args);
  };
  c.Click += e2;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!