How to fire async events and c++/clr

G

Guest

Greetings,

I am trying to fire aysnc events in c++/clr, and I can't seem to get it to
work.
It seems to work fine in c#, but when I try c++/clr, I can't seem to get it
to compile in the c++/clr class.

I.) Event Testing in C#, which works fine:
public class CSharpEventTest
{
public event CSharpDelegate AsyncEvent = null;
public event CSharpDelegate SyncEvent = null;

public void FireAsyncEvent(string message)
{
if (AsyncEvent == null) return;

AsyncEvent.BeginInvoke(message, null, this);
}

public void FireSyncEvent(string message)
{
if (SyncEvent == null) return;

SyncEvent(message);
}

}


II. Event Testing in MC++, which doesn't compile correctly.
public delegate bool MCDelegate(System::String^ errorCode);

public ref class MCEventTesting
{
public:
MCEventTesting(void);

event MCDelegate^ EventSync;
event MCDelegate^ EventASync;

public:
void FireEventAsync(System::String^ errorCode)
{
// Doesn't compile, gives an error:
//"invalid argument for delegate constructor; delegate target needs to be a
// pointer to a member function"
MyErrorDelegate^ delg = gcnew MyErrorDelegate(EventASync(errorCode));
delg.BeginInvoke(NULL, delg);
}

// Works fine
void FireEventSync(System::String^ errorCode)
{
EventSync(errorCode);
}
};

Thanks for any suggestions!
 
T

Tamas Demjen

BartMan said:
public:
void FireEventAsync(System::String^ errorCode)
{
// Doesn't compile, gives an error:
//"invalid argument for delegate constructor; delegate target needs to be a
// pointer to a member function"
MyErrorDelegate^ delg = gcnew MyErrorDelegate(EventASync(errorCode));

MyErrorDelegate^ delg = gcnew MyErrorDelegate(this,
&MCEventTesting::EventASync);

The first argument (this) is a handle to the handler class. The second
argument (&MCEventTesting::EventASync) is a pointer to the handler function.

Tom
 
G

Guest

Hello Tamas,

Thanks for the reply. I tried your recommendation for the method.
MyErrorDelegate^ delg = gcnew MyErrorDelegate(this,
&MCEventTesting::EventASync);

But I get the following error:
Error 1 error C3364: invalid argument for delegate constructor; delegate
target needs to be a pointer to a member function

For some reason the "event MCDelegate^ EventASync;" is not working as a
member function.

Any ideas?
 
T

Tamas Demjen

BartMan said:
But I get the following error:
Error 1 error C3364: invalid argument for delegate constructor; delegate
target needs to be a pointer to a member function

You didn't disclose the declaration of MyErrorDelegate, but it looks
like it's not compatible with the handler. Your event handler must have
the exact same arguments and return type as the delegate. For example,
MCDelegate is declared

public delegate bool MCDelegate(System::String^ errorCode);

So the event handler must be declared

bool xxx(System::String^ errorCode);

Tom
 
G

Guest

You didn't disclose the declaration of MyErrorDelegate, but it looks
like it's not compatible with the handler. Your event handler must have
the exact same arguments and return type as the delegate. For example,
MCDelegate is declared

Opps a typo on my part the delegate was declared, and the event is declared
below, and it has the same values, so I don't understand how it cannot
compile.
Especially since the c# works fine?

// Here is the Delegate:
public delegate bool MCDelegate(System::String^ errorCode);

public ref class MCEventTesting
{
public:
MCEventTesting(void);

event MCDelegate^ SyncEvent;
event MCDelegate^ AsyncEvent; // Async Event?????

public:
// Fire the event as an async event.
void fireErrorEventAsync(System::String^ errorCode)
{
// ERROR: "Complains that it must be a pointer to a member function."
MCDelegate^ delg = gcnew MCDelegate(this,&MCEventTesting::AsyncEvent);
AsyncEvent->BeginInvoke("test",nullptr,this);

// Also tried this, it didn't work complained that it needs to be a data
member.
// MCEventTesting::AsyncEvent->BeginInvoke(errorCode,nullptr,nullptr);
}

// Works fine.
void fireSyncEvent(System::String^ errorCode)
{
SyncEvent(errorCode);
}
};
 
B

Ben Voigt

BartMan said:
Opps a typo on my part the delegate was declared, and the event is
declared
below, and it has the same values, so I don't understand how it cannot
compile.
Especially since the c# works fine?

// Here is the Delegate:
public delegate bool MCDelegate(System::String^ errorCode);

public ref class MCEventTesting
{
public:
MCEventTesting(void);

event MCDelegate^ SyncEvent;
event MCDelegate^ AsyncEvent; // Async Event?????

public:
// Fire the event as an async event.
void fireErrorEventAsync(System::String^ errorCode)
{
// ERROR: "Complains that it must be a pointer to a member function."
MCDelegate^ delg = gcnew MCDelegate(this,&MCEventTesting::AsyncEvent);
AsyncEvent->BeginInvoke("test",nullptr,this);

// Also tried this, it didn't work complained that it needs to be a data
member.
// MCEventTesting::AsyncEvent->BeginInvoke(errorCode,nullptr,nullptr);

Use this along with a custom event:

private:
MCDelegate^ AsyncHandlerList;

public:
event MCDelegate^ Async {
MCDelegate^ add(MCDelegate^ d) { return AsyncHandlerList =
Delegate::Combine(AsyncHandlerList, d); }
MCDelegate^ remove(MCDelegate^ d) { return AsyncHandlerList =
Delegate::Remove(AsyncHandlerList, d); }
}

void fireErrorEventAsync(System::String^ errorCode)
MCEventTesting::AsyncHandlerList->BeginInvoke(errorCode,nullptr,nullptr);
}
 
G

Guest

event MCDelegate^ Async {
MCDelegate^ add(MCDelegate^ d) { return AsyncHandlerList =
Delegate::Combine(AsyncHandlerList, d); }
MCDelegate^ remove(MCDelegate^ d) { return AsyncHandlerList =
Delegate::Remove(AsyncHandlerList, d); }
}
Hello Ben,

Thanks for the reply. The above mentioned code issues the following error:
Error 1 error C3919: 'Async::add': function must have type 'void (MCDelegate
^)'

I tried changing it to "void add(MCDelegate^ d) {....}", but that didn't
seem to work either.
 
B

Ben Voigt

BartMan said:
Hello Ben,

Thanks for the reply. The above mentioned code issues the following
error:
Error 1 error C3919: 'Async::add': function must have type 'void
(MCDelegate
^)'

I tried changing it to "void add(MCDelegate^ d) {....}", but that didn't
seem to work either.

also take out the word return. Oh, and the += and -= operators do work in
C++. Here's a snippet out of my own code:

virtual event System::EventHandler^ Closed

{

void add( System::EventHandler^ handler )

{

CloseHandlers += handler;

}

void remove( System::EventHandler^ handler )

{

CloseHandlers += handler;

}

}
 
G

Guest

also take out the word return. Oh, and the += and -= operators do work in
C++. Here's a snippet out of my own code:

virtual event System::EventHandler^ Closed

{

void add( System::EventHandler^ handler )

{

CloseHandlers += handler;

}

void remove( System::EventHandler^ handler )

{

CloseHandlers += handler;

}

}

Thanks that is very good to know. I did not know that operator support has
been added in c++/clr. Thank for all your help, it is exactly what I needed.

Here is my final version which seems to execute properly.

public delegate bool MCDelegate(System::String^ errorCode);

public ref class MCEventTesting
{
public:
MCEventTesting(void);

event MCDelegate^ SyncEvent;

private:
MCDelegate^ AsyncHandlerList;

public:
event MCDelegate^ Async
{

void add(MCDelegate^ d)
{
AsyncHandlerList =
(MCDelegate^)System::Delegate::Combine(AsyncHandlerList, d);
}

void remove(MCDelegate^ d)
{
AsyncHandlerList = (MCDelegate^)System::Delegate::Remove(AsyncHandlerList,
d);
}
}

public:
void fireErrorEventAsync(System::String^ errorCode)
{
MCEventTesting::AsyncHandlerList->BeginInvoke(errorCode,nullptr,nullptr);
}

void fireSyncEvent(System::String^ errorCode)
{
SyncEvent(errorCode);
}
};
 
B

Ben Voigt

Thanks that is very good to know. I did not know that operator support
has
been added in c++/clr. Thank for all your help, it is exactly what I
needed.

Here is my final version which seems to execute properly.

public delegate bool MCDelegate(System::String^ errorCode);

public ref class MCEventTesting
{
public:
MCEventTesting(void);

event MCDelegate^ SyncEvent;

private:
MCDelegate^ AsyncHandlerList;

public:
event MCDelegate^ Async
{

void add(MCDelegate^ d)
{
AsyncHandlerList =
(MCDelegate^)System::Delegate::Combine(AsyncHandlerList, d);
As I showed you with my code, this can be shortened to: AsyncHandlerList +=
d
}

void remove(MCDelegate^ d)
{
AsyncHandlerList = (MCDelegate^)System::Delegate::Remove(AsyncHandlerList,
d);
And here, AsyncHandlerList -= d
}
}

public:
void fireErrorEventAsync(System::String^ errorCode)
{
MCEventTesting::AsyncHandlerList->BeginInvoke(errorCode,nullptr,nullptr);
Don't forget to get the IAsyncResult and call EndInvoke later. And yes,
this is a pain, but it's required. You can pass an anonymous method as the
callback to BeginInvoke to help with this.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top