locked
Exception raised during event call in a lambda function

    Question

  • Hi,

    I'm Learning metro programming and I really do not understand why we can't call an event from an async task. Can somebody help me ? What is wrong with my code ?

    namespace test
    {
    	public delegate void FunctionHandler(int);
    
    	public ref class Class1 sealed
    	{
    	public:
    		event FunctionHandler^ FunctionEvent;
    		void Run(void) {
    			//FunctionEvent(0); //Work
    			Windows::Foundation::IAsyncAction^ action = create_async([this] (void) -> void {
    				this->FunctionEvent(0); //Do not work, what happened ? DisconnectedException raised :/
    			});
    
    			create_task([this] (void) -> void {
    				this->FunctionEvent(0); //Same error
    			});
    		}
    	};
    
    	public ref class Class2 sealed
    	{
    	public:
    		Class2(void) {
    			Class1 ^c = ref new Class1();
    			c->FunctionEvent += ref new FunctionHandler(this, &Class2::Function);
    			c->Run();
    		}
    
    		void Function(int i) { }
    
    	};
    }

    Monday, June 25, 2012 12:31 PM

Answers

  • The delegate form you are using to bind to the event:

    c->FunctionEvent += ref new FunctionHandler(this, &Class2::Function);

    takes a weak reference on the "this" argument.   It's likely that by the time the asynchronous task which raises the event runs, Class2 has already been destroyed as the event handler is not keeping it alive.  The exception is probably from the weak reference not resolving.  If you intend the event handler to keep your instance of Class2 alive, you can instead do something like:

    c->FunctionEvent += ref new FunctionHandler( [this](int i) { Function(i); });

    The lambda capture of "this" will be a strong reference and will keep the instance of Class2 alive as long as the event is registered.
    • Proposed as answer by Jesse Jiang Tuesday, June 26, 2012 6:28 AM
    • Marked as answer by dadalailamah Tuesday, June 26, 2012 1:15 PM
    Monday, June 25, 2012 6:59 PM

All replies

  • The delegate form you are using to bind to the event:

    c->FunctionEvent += ref new FunctionHandler(this, &Class2::Function);

    takes a weak reference on the "this" argument.   It's likely that by the time the asynchronous task which raises the event runs, Class2 has already been destroyed as the event handler is not keeping it alive.  The exception is probably from the weak reference not resolving.  If you intend the event handler to keep your instance of Class2 alive, you can instead do something like:

    c->FunctionEvent += ref new FunctionHandler( [this](int i) { Function(i); });

    The lambda capture of "this" will be a strong reference and will keep the instance of Class2 alive as long as the event is registered.
    • Proposed as answer by Jesse Jiang Tuesday, June 26, 2012 6:28 AM
    • Marked as answer by dadalailamah Tuesday, June 26, 2012 1:15 PM
    Monday, June 25, 2012 6:59 PM
  • thank you very much, it solved my problem ! :D
    Tuesday, June 26, 2012 1:15 PM