wx.PyEvent cloning

Hi,

I’m having an issue with wx.PyEvents while testing my application with Phoenix I think it’s related to this change to wx.PyEvent’s Clone method: https://github.com/wxWidgets/Phoenix/commit/360e3e6b2f9f14429a992a47e9a4df93202f9fee

I have tried unsuccessfully to come up with a small reproducible code sample demonstrating the problem, but I’ll try to describe it.

I define a custom event class, using a similar method to wx.lib.newevent’s NewEvent, something like this:

class MyPyEvent(wx.PyEvent):

def __init__(self, **kw):

    wx.PyEvent.__init__(self)

    if 'phoenix' in wx.PlatformInfo:

        self._getAttrDict().update(kw)

    else:

        self.__dict__.update(kw)

I then instantiate an event and give it a “nextEvent” attribute:

event = MyPyEvent(nextEvent=anotherEvent)

This event is posted with wx.PostEvent and then handled by an event handler.

The event handler starts a thread, passing the event as an argument.

The thread’s worker does some potentially time-consuming stuff and then calls wx.PostEvent(event.nextEvent)

When testing with Phoenix, I have found that unless I explicitly Clone() the event before passing it from the event handler to the thread’s worker, sometimes the event’s “nextEvent” attribute is missing at the time the thread’s worker tries to post the nextEvent, and that calling event._getAttrDict().keys() in the thread’s worker can give:

sys.stdout.write("Check. event._getAttrDict().keys() = %s\n" % event._getAttrDict().keys())

RuntimeError: wrapped C/C++ object of type Event has been deleted

Is this expected behaviour (that I should need to Clone() the event before passing it from an event handler to a thread worker)?

Thanks,

James

James Wettenhall wrote:

Hi,

I’m having an issue with wx.PyEvents while testing my application with Phoenix I think it’s related to this change to wx.PyEvent’s Clone method: https://github.com/wxWidgets/Phoenix/commit/360e3e6b2f9f14429a992a47e9a4df93202f9fee

I
have tried unsuccessfully to come up with a small reproducible code sample demonstrating the problem, but I’ll try to describe it.

I
define a custom event class, using a similar method to wx.lib.newevent’s NewEvent, something like this:

class MyPyEvent(wx.PyEvent):

def __init__(self, **kw):
    wx.PyEvent.__init__(self)
    if 'phoenix' in wx.PlatformInfo:
        self._getAttrDict().update(kw)
    else:
        self.__dict__.update(kw)

I then instantiate an event and give it a “nextEvent” attribute:

event = MyPyEvent(nextEvent=anotherEvent)

This
event is posted with wx.PostEvent
and then handled by an event handler.

The event handler starts a thread, passing the event as an argument.

The thread’s worker does some potentially time-consuming stuff and then calls wx.PostEvent(event.nextEvent)

When
testing with Phoenix, I have found that unless I explicitly Clone() the event before passing it
from the event handler to the thread’s worker, sometimes the event’s “nextEvent” attribute is missing at the time the thread’s worker tries to post the nextEvent, and that calling event._getAttrDict().keys() in the thread’s worker can
give:

sys.stdout.write("Check. event._getAttrDict().keys() = %s\n" % event._getAttrDict().keys())

RuntimeError: wrapped C/C++ object of type Event has been deleted

Is this expected behaviour (that I should need to Clone() the event before passing it from an event
handler to a thread worker)?

No, it shouldn’t be needed. Please make a small runnable sample I can use for debugging the problem.

···


Robin Dunn

Software Craftsman

http://wxPython.org

Robin,

Thanks for the prompt reply.

Small runnable sample posted here: https://github.com/wxWidgets/Phoenix/issues/265

Cheers,

James

Ok, I wasn’t thinking things all the way through yesterday. It is working as expected and the event should be cloned before giving it to the worker thread.

Basically, Clone is called when wx.PostEvent is called, and the clone is put on the pending event queue. Later, after the event has been processed and its event handler returns, it is removed from the queue and that destroys the C++ object for the cloned event. In your example it appears that it is happening when the thread blocks momentarily for setting the busy cursor.

Robin

···

On Wednesday, April 5, 2017 at 9:09:35 PM UTC-7, James Wettenhall wrote:

Robin,

Thanks for the prompt reply.

Small runnable sample posted here: https://github.com/wxWidgets/Phoenix/issues/265

Cheers,

James