简体   繁体   中英

How to use event handler with delegate from child class with interface

I've done some searching here and haven't been able to get a clear answer to my problem. I have a several child classes all with 1 interface. I have a parent class that contains a variable and this variable is created as a new instances of one of those child classes depending on external params. Here's some code:

public interface I
{
    public delegate void ExecutionCompletedHandler(bool status);
    public event ExecutionCompletedHandler executionCompleted;
    public void Execute();
}

public class C1 : I
{
    public void Execute()
    {
        // Create background worker and execute DoStuff
    }

    public void BackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        bool status = (bool)e.Result;
        this.executionCompleted(true);
    }
}

public class C2 : I
{
    // Same setup as C1
}

public class C3 : I
{
    // Same setup as C1
}

public class MyManager
{
    public void doStuff(int val)
    {
        var compObj = null;
        // compObj is now instantiated as new instance of C1, C2 or C3 depending on val
        // ex: compObj = new C1();

        compObj.executionCompleted += new I.ExecutionCompletedHandler(executionCompletedHandler);
        compObj.Execute();
    }

    private void executionCompletedHandler(bool status)
    {
        // Do stuff with status and exit gracefully
    }
}

This is what I'd like to do but I know it's not right. I feel as if I'm 90% of the way there. It's saying that the executionCompleted variable in the C1 class is hiding the interface's variable. I've tried to follow various guides and examples but haven't been able to figure this out. Thanks!

Edit: I'm using .NET 4.0 in Visual Studio 2010.

EDIT 2: I was able to figure it out with help from @NikProtsman...I converted the interface to an abstract class, and in that abstract class, implemented a CompleteExecution function. In this function, I would call the event handler. In the C1/C2/C3 classes, when background worker is finished executing, I would call this method. Works perfectly. We're in the process of upgrading to VS 2019 and after this, I'm going to push to make that happen quicker! Thanks!

Try this:

In your interface, change Execute to:

public Task Execute();

In your Class C1:

//Add this line to conform to Interface
public event I.ExecutionCompleteHandler executionCompleted;

public async Task Execute()
{
    // Create background worker and execute DoStuff
    await DoStuff();
    // You'll need to supply appropriate args here
    BackgroundWorkerCompleted(this, args);
}

public void BackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    bool status = (bool)e.Result;
    //Changed this line, assumed you needed the status from the line above
    executionCompleted?.invoke(status);
}

Next your MyManager should look like this:

public class MyManager
{
    public async Task doStuff(int val)
    {
        var compObj = null
        // compObj is now instantiated as new instance of C1, C2 or C3 depending on val
        compObj = new C1();

        // Subscribe to the 'executioncompleted' event in your new instance
        compObj.executionCompleted += HandleExecutionComplete;
        // Execute your code
        await compObj.Execute();
        // Unsubscribe from the event (cleaning up after yourself)
        compObj.executionCompleted -= HandleExecutionComplete;
    }

    private void HandleExecutionComplete(bool status)
    {
        // Do stuff with status and exit gracefully
    }
}

The key point here is assigning the Execution Handler properly in your Manager, and then using it to subscribe to the C1 class event. Inside the C1 class, use a Task for DoStuff, and await it in Execute which becomes an async Task. Once DoStuff is done, the WorkerCompleted task runs, executes your handler, and off you go.

This can all be simplified somewhat but that is outside the scope of this question. The idea is how the control flow will work and using async calls with await to make sure your program waits for what it needs, and then continues, and how you subscribe to that event externally.

Just be sure to await your MyManager.doStuff call on the outside as well, otherwise any results you are waiting for will not get picked up in time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM