ExternalEvent cleanup

ExternalEvent cleanup

tamas.deri
Advocate Advocate
644 Views
8 Replies
Message 1 of 9

ExternalEvent cleanup

tamas.deri
Advocate
Advocate

The other day, I was wondering whether or not I should clean up my ExternalEvents when I close my modeless windows.

The question came up when I needed to unsubscribe from certain events upon closing my windows, and I had no idea what happens to the ViewModel object and the ExternalEvent it references. Will the garbage collector clean up everything when the window is closed, or should I specifically dispose my ExternalEvent as well?

0 Likes
Accepted solutions (1)
645 Views
8 Replies
Replies (8)
Message 2 of 9

ankofl
Advocate
Advocate

For more guarantee, you can try calling Dispose() for ExternalEvent in the closing event of your non-modal window

 

 

public static WinRoom winRoom = null; // Your WinRoom.xaml (Window)
public static ExternalEvent exEvent = null;

public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    Document Doc = commandData.Application.ActiveUIDocument.Document;
    ts = new Transaction(Doc, "name");
    ts.Start();
    exEvent = ExternalEvent.Create(new Hand());

    winRoom = new WinRoom();
    winRoom.Closed += WinRoom_Closed;
    winRoom.Show();

    ts.Commit();
    return Result.Succeeded;
}

public class Hand : IExternalEventHandler
{
    public void Execute(UIApplication app)
    {
        Document Doc = app.ActiveUIDocument.Document;
        Transaction ts = new Transaction(Doc, "name");
        ts.Start();

        ts.Commit();
    }

    public string GetName()
    {
        return "name";
    }
}

private void WinRoom_Closed(object sender, EventArgs e)
{
    exEvent.Dispose();
}

 

 

 

0 Likes
Message 3 of 9

tamas.deri
Advocate
Advocate

Yep, thats what I've tried, but unfortunately I have to call Raise() for that specific event when I'm closing the window, and disposing immediately after raising will prevent the execution. I've tried sleep before disposing, but it never gets executed. I guess it waits for the window to be closed, and tries to execute after, but there is nothing to be executed.

0 Likes
Message 4 of 9

ankofl
Advocate
Advocate

I think it's worth looking through the debugger to see if the Raise() call occurs after or during window closure, and if it is called, look at what is happening through the debugger

0 Likes
Message 5 of 9

tamas.deri
Advocate
Advocate

I've tried but I didn't get too far. The breakpoint in the Execute() method never gets hit, if I dispose the ExternalEvent after Raise(). What happens if I just remove the reference of the ExternalEvent from the ViewModel? (setting the variable to null) I suspect it should be enough, because it will be released, and it should be cleaned up by the garbage collector. What any other consequences could I have if I do this?

0 Likes
Message 6 of 9

ankofl
Advocate
Advocate

I think I've figured out your problem: you create an ExternalEvent inside an instance of the Window object. If so, try to separate ExternalEvent from Window (Viewmode) by placing it in an instance of a class implementing IExternalCommand. Thus, the ExternalEvent will be independent of the Window even after Window is closed

0 Likes
Message 7 of 9

tamas.deri
Advocate
Advocate

But since I'm using a modeless window the ExternalCommand returns as soon as the window is opened, so even if I instantiate my ExternalEvent in the ExternalCommand I still have to pass it to the window to Raise it when needed. Or am I misunderstanding you?

0 Likes
Message 8 of 9

ankofl
Advocate
Advocate
Accepted solution

Да, вы меня правильно поняли. Я тоже сначала так думал, но если пометить ExternalEvent как "статический"

 

 

public static ExternalEvent exEvent = null;

 

 

 тогда к нему можно будет получить доступ даже после завершения возврата Result.Succeeded;

 

 

public static WinRoom winRoom = null;
public static ExternalEvent exEvent = null;
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    Doc = commandData.Application.ActiveUIDocument.Document;
    ts = new Transaction(Doc, "name");
    ts.Start();

    winRoom = new WinRoom();

    winRoom.btnUpdate.Click += BtnUpdateRooms_Click;
    
    exEvent = ExternalEvent.Create(new Handler());

    winRoom.Closed += WinRoom_Closed;
    winRoom.Show();

    ts.Commit();
    return Result.Succeeded;
}

private void BtnUpdateRooms_Click(object sender, RoutedEventArgs e)
{
    exEvent.Raise();
}

 

 

В этом примере мы получаем доступ к статическому полю public static ExternalEvent exEvent из события BtnUpdateRooms_Click после:

 

 

public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
return Result.Succeeded;

 

 

 

0 Likes
Message 9 of 9

tamas.deri
Advocate
Advocate

Thanks for the tipp, I went this way. I store the external event in a static variable of the ExternalCommand, and only instantiate it if it is null. So instead of disposing it I reuse the same instance everytime the window is opened again.