Dilshod
Dilshod

Reputation: 3311

Firing the event B after finishing the event A

Sorry if the title doesn't make good sense.

I have two events. Event A, B and I have method M1 and M2. M1 is subscribed to event A. When method M1 fired it fires method M2 which raised the event B.

Here is the scheme:

A raised
  M1 fired
    M2 fired
      B raised
        ----
        ----
      B ended
    M2 ended
  M1 ended
A ended

What I want is wait until A ended and raise B. Because the subscribers of the B can not do their stuff when A is working.

This is What I want.

A raised
  M1 fired
    somehow specify to fire M2 right after A finished
  M1 ended
A ended
M2 fired
   B raised
      ----
      ----
   B ended
M2 ended

What is the efficient way to do this?

Thanks for the help!

Upvotes: 0

Views: 143

Answers (2)

Alex
Alex

Reputation: 13224

How about something like this:

public class EventThing
{
    public event Action A;
    public event Action B;

    public EventThing()
    {
        A += () =>
        {
            Action next = M1();
            if (next != null)
                next();
        };
    }
    public void FireA()
    {
        var AHandlers = A;
        if (AHAndlers != null)
        {
            foreach (Action action in (AHAndlers as MulticastDelegate).GetInvocationList().Reverse())
                action();
        }
    }
    private Action M1()
    {
        Console.WriteLine("Running M1");
        return M2;
    }
    private void M2()
    {
        Console.WriteLine("Running M2");
        if (B != null)
            B();
    }
}

static void Main(string[] args)
{
    var eventThing = new EventThing();
    eventThing.A += () => Console.WriteLine("Performing A");
    eventThing.B += () => Console.WriteLine("Performing B");
    eventThing.FireA();
    Console.ReadLine();
}

With output:

Performing A
Running M1 
Running M2
Performing B

Upvotes: 0

Servy
Servy

Reputation: 203816

Have M1 Start a new Task or Thread that will run M2. That way M1 will be able to finish executing and then have M2 start at a later time. If there is a synchronization mechanism that prevents M2 from doing anything until M1 finishes, the order of execution will be as you showed.

Example:

public class Foo
{
    public event Action A;
    public event Action B;

    public Foo()
    {
        A += M1;
    }

    private object key = new object();
    private void M1()
    {
        lock (key)
        {
            Task.Run(() => M2());
        }
    }
    private void M2()
    {
        lock (key)
        {
            if (B != null)
                B();
        }
    }
}

Upvotes: 3

Related Questions