473,787 Members | 2,928 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

BeginInvoke on a delegate

I'm trying to call a function on a background thread in a C++/CLI (VS 2005)
application compiled with /clr. I store a delegate reference in a module-level
gcroot. When I call BeginInvoke on the delegate I get a RemotingExcepti on. The
inner exception says "Pointer types cannot be passed in a remote call". A code
example that demonstrates the problem appears below.

Am I even wiring up the delegate/BeginInvoke/EndInvoke stuff correctly? The
documentation is pretty sketchy.

TIA - Bob

----- Code example -----

#include <gcroot.h>

using namespace System;

// Class with no members
class MyClass {
};

// Forward references
void BackgroundWorke r(MyClass& myClass);
void _Callback(IAsyn cResult ^ar);

// Module-level data
delegate void BackgroundWorke rDelegType(MyCl ass& myClass);

static gcroot<Backgrou ndWorkerDelegTy pe^>
m_BackgroundWor kerDeleg
= gcnew BackgroundWorke rDelegType(&Bac kgroundWorker);

static gcroot<AsyncCal lback^>
m_callbackDeleg
= gcnew AsyncCallback(& _Callback);

// Main program
int main(array<Syst em::String ^^args)
{
MyClass myClass;
// RemotingExcepti on: Pointer types cannot be passed in a remote call
m_BackgroundWor kerDeleg->BeginInvoke(my Class, m_callbackDeleg , nullptr);
return 0;
}

void BackgroundWorke r(MyClass& myClass)
{
Console::WriteL ine("In BackgroundWorke r");
}

// Routine called when the asynchronous call completes
void _Callback(IAsyn cResult ^ar)
{
m_BackgroundWor kerDeleg->EndInvoke(ar );
}
Jun 27 '08 #1
9 3989
I simplified the sample app by removing all of the gcroot stuff. The resultant
app still gets the same error. I'm obviously doing something fundamentally
wrong, but the docs make no mention of how to use BeginInvoke with a C++
delegate.

----- New sample app ------

#include <gcroot.h>

using namespace System;

// Class with no members
class MyClass {
};

// Forward references
void BackgroundWorke r(MyClass& myClass);
void Callback(IAsync Result ^ar);

// Module-level data
delegate void BackgroundWorke rDelegType(MyCl ass& myClass);

// Main program
int main(array<Syst em::String ^^args)
{
MyClass myClass;
BackgroundWorke rDelegType^ d = gcnew
BackgroundWorke rDelegType(&Bac kgroundWorker);
AsyncCallback^ cb = gcnew AsyncCallback(& Callback);
// RemotingExcepti on: Pointer types cannot be passed in a remote call
d->BeginInvoke(my Class, cb, d);
return 0;
}

void BackgroundWorke r(MyClass& myClass)
{
Console::WriteL ine("In BackgroundWorke r");
}

// Routine called when the asynchronous call completes
void Callback(IAsync Result ^ar)
{
BackgroundWorke rDelegType^ d =
static_cast<Bac kgroundWorkerDe legType^>(ar->AsyncState);
d->EndInvoke(ar );
}
Jun 27 '08 #2
It occurs to me that the problem probably has to do with the fact that the
routine I am trying to call with BeginInvoke takes an argument that is a
reference to a native object. Delegates, being part of the CLR, probably
don't know how do deal with native objects. So, how can I pass a native
object (in my actual application it's an STL map) to a routine that I want
to execute on a background (thread pool) thread?

And, if my guess (above) is correct, why does is happily compile? You'd
think that the compiler would complain when it sees me trying to create a
delegate with a native object reference as an argument.

Or maybe I'm still totally clueless and totally off base...

Jun 27 '08 #3
Hi Bob,
Your analysis is correct. The problem here is that the native type object
"myClass" is passed as a parameter to BeginInvoke. There are two ways to
work around this issue, one is changing your MyClass type from native to
managed, and the other one is using a wrapper managed class to wrap your
native type object. For example:
=============== =============== =======
class MyClass {
public:
int Age;
string Name;
};

template <typename T>
ref struct MyWrapperClass
{
MyWrapperClass( ) : m_ptr(0) {}
MyWrapperClass( T* ptr) : m_ptr(ptr) {}
MyWrapperClass( MyWrapperClass< T>% right) : m_ptr(right.Rel ease())
{
}
T* operator->()
{
return m_ptr;
}

T* Get()
{
return m_ptr;
}

T* Release()
{
T* released = m_ptr;
m_ptr = 0;
return released;
}

private:
T* m_ptr;
};
// Forward references
void BackgroundWorke r(MyWrapperClas s<MyClassmyWrap perCls);
void Callback(IAsync Result ^ar);

// Module-level data
delegate void BackgroundWorke rDelegType(MyWr apperClass<MyCl ass>
myWrapperCls);

// Main program
int main(array<Syst em::String ^^args)
{
MyClass myClass;
myClass.Age = 26;
myClass.Name="B ill";

MyWrapperClass< MyClassmyWrappe rCls(&myClass);
BackgroundWorke rDelegType^ d = gcnew
BackgroundWorke rDelegType(Back groundWorker);
AsyncCallback^ cb = gcnew AsyncCallback(C allback);
d->BeginInvoke(my WrapperCls, cb, d);

Console::Read() ;
return 0;
}

void BackgroundWorke r(MyWrapperClas s<MyClassmyWrap perCls)
{
Console::WriteL ine("In BackgroundWorke r");
Console::WriteL ine(myWrapperCl s->Age);
Console::WriteL ine(myWrapperCl s->Name.c_str() );
}

// Routine called when the asynchronous call completes
void Callback(IAsync Result ^ar)
{
BackgroundWorke rDelegType^ d =
static_cast<Bac kgroundWorkerDe legType^>(ar->AsyncState);
d->EndInvoke(ar );
}
=============== =============== =============== ===

For mix using native and managed types, you may also refer to this article:
Best Practices for Writing Efficient and Reliable Code with C++/CLI
http://msdn.microsoft.com/en-us/libr...37(VS.80).aspx

Hope this helps. If you have any other questions or concerns, please feel
free to let me know.

Best regards,
Charles Wang
Microsoft Online Community Support
=============== =============== =============== ==============
Delighting our customers is our #1 priority. We welcome your
comments and suggestions about how we can improve the
support we provide to you. Please feel free to let my manager
know what you think of the level of service provided. You can
send feedback directly to my manager at: ms****@microsof t.com.
=============== =============== =============== ==============
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscripti...ult.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for
non-urgent issues where an initial response from the community
or a Microsoft Support Engineer within 1 business day is acceptable.
Please note that each follow up response may take approximately
2 business days as the support professional working with you may
need further investigation to reach the most efficient resolution.
The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by
contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscripti...t/default.aspx.
=============== =============== =============== ===============
This posting is provided "AS IS" with no warranties, and confers no rights.
=============== =============== =============== ============


Jun 27 '08 #4
Thanks Charles, that is exactly what I'm looking for!

I looked at the article you referenced in your reply
(http://msdn.microsoft.com/en-us/libr...37(VS.80).aspx) and that
author provides a more complete implementation of your managed wrapper class
(shown below). I have a couple of questions about his code:

1. Why does the destructor call "delete m_ptr"? This wrapper didn't
allocate that memory. In my application, I have a module-level STL map that
I pass as an argument to some function. That function needs to wrap the map
reference in this managed wrapper so that it can pass it as an argument to a
managed function (in my case [delegate].BeginInvoke). But I certainly don't
want the managed wrapper to try to delete my map when the wrapper's
destructor is called!

2. What's the "!AutoPtr() " thing all about?

TIA - Bob

----- Code -----

template <typename T>
ref struct AutoPtr
{
AutoPtr() : m_ptr(0) {}
AutoPtr(T* ptr) : m_ptr(ptr) {}
AutoPtr(AutoPtr <T>% right) : m_ptr(right.Rel ease()) {}

~AutoPtr()
{
delete m_ptr;
m_ptr = 0;
}
!AutoPtr()
{
ASSERT(0 == m_ptr);
delete m_ptr;
}
T* operator->()
{
ASSERT(0 != m_ptr);
return m_ptr;
}

T* Get()
{
return m_ptr;
}
T* Release()
{
T* released = m_ptr;
m_ptr = 0;
return released;
}
void Reset()
{
Reset(0);
}
void Reset(T* ptr)
{
if (ptr != m_ptr)
{
delete m_ptr;
m_ptr = ptr;
}
}

private:
T* m_ptr;
};

Jun 27 '08 #5
Bob Altman wrote:
I looked at the article you referenced in your reply
(http://msdn.microsoft.com/en-us/libr...37(VS.80).aspx) and that
author provides a more complete implementation of your managed wrapper
class (shown below). I have a couple of questions about his code:

1. Why does the destructor call "delete m_ptr"? This wrapper didn't
allocate that memory.
Those are the semantics of the class -- passing it a pointer means it'll
take ownership of the allocated memory. The STL's auto_ptr works the same
way. If that's not what you want, you are of course free not to do it.
However, take care that in doing this, it's possible for the managed class
to hold a dangling pointer if you free the object while it's still
referenced from managed code. This, as you can imagine, is very bad.
2. What's the "!AutoPtr() " thing all about?
That's the managed finalizer, not to be confused with the destructor. When
the object is garbage collected, the finalizer will be run. You typically
don't need this because C++ encourages you to manage objects explicitly, so
the destructor would take care of releasing resources.

--
J.
Jun 27 '08 #6

"Jeroen Mostert" <jm******@xs4al l.nlwrote in message
news:48******** *************** @news.xs4all.nl ...
Bob Altman wrote:
>I looked at the article you referenced in your reply
(http://msdn.microsoft.com/en-us/libr...37(VS.80).aspx) and that
author provides a more complete implementation of your managed wrapper class
(shown below). I have a couple of questions about his code:

1. Why does the destructor call "delete m_ptr"? This wrapper didn't allocate
that memory.

Those are the semantics of the class -- passing it a pointer means it'll take
ownership of the allocated memory. The STL's auto_ptr works the same way.
Aha! That also explains why the copy constructor modifies the "right" object by
clearing its pointer to the native data. That's what the author meant by
"transfer of ownership semantics".

But that still leaves the question of whether or not it's even correct to call
delete on the pointer. What if the native object was allocated on the stack,
e.g.

void MySub() {
MyNativeClass c;
MyOtherSub(c);
}

void MyOtherSub(MyNa tiveClass& c) {
// At this point we have no idea whether
// c was allocated on the stack or the heap
AutoPtr<MyNativ eClassp(&c);
}

Assuming I got the syntax at least kind of correct, what will happen when the
AutoPtr goes out of scope and its destructor tries to delete c?
Jun 27 '08 #7
Bob Altman wrote:
"Jeroen Mostert" <jm******@xs4al l.nlwrote in message
news:48******** *************** @news.xs4all.nl ...
>Bob Altman wrote:
>>I looked at the article you referenced in your reply
(http://msdn.microsoft.com/en-us/libr...37(VS.80).aspx) and that
author provides a more complete implementation of your managed wrapper class
(shown below). I have a couple of questions about his code:

1. Why does the destructor call "delete m_ptr"? This wrapper didn't allocate
that memory.
Those are the semantics of the class -- passing it a pointer means it'll take
ownership of the allocated memory. The STL's auto_ptr works the same way.

Aha! That also explains why the copy constructor modifies the "right" object by
clearing its pointer to the native data. That's what the author meant by
"transfer of ownership semantics".

But that still leaves the question of whether or not it's even correct to call
delete on the pointer. What if the native object was allocated on the stack,
e.g.

void MySub() {
MyNativeClass c;
MyOtherSub(c);
}

void MyOtherSub(MyNa tiveClass& c) {
// At this point we have no idea whether
// c was allocated on the stack or the heap
AutoPtr<MyNativ eClassp(&c);
}
It hurts when you move your arm that way, doesn't it? :-)
Assuming I got the syntax at least kind of correct, what will happen when the
AutoPtr goes out of scope and its destructor tries to delete c?
I'm pretty sure demons will fly out of your nose, since that invokes
undefined behavior.

The reason the class is named AutoPtr is to evoke images of the STL's
auto_ptr, which *also* isn't used this way. Indeed, there's no point at all
to using auto_ptr on objects you didn't construct yourself (as MyOtherSub is
doing here).

You can still write MyOtherSub this way, with some care:

void MyOtherSub(MyNa tiveClass& c) {
AutoPtr<MyNativ eClassp(new MyNativeClass(c ));
}

But of course copying the object isn't always desirable or even possible.

If you want to pass a stack-allocated objects, don't use smart pointers. On
the other hand, smart pointers are a pretty good approach to avoiding memory
leaks for objects you *can't* stack-allocate.

--
J.
Jun 27 '08 #8
It hurts when you move your arm that way, doesn't it? :-)

Yeah. My doctor told me not to do that any more.
If you want to pass a stack-allocated objects, don't use smart pointers. On
the other hand, smart pointers are a pretty good approach to avoiding memory
leaks for objects you *can't* stack-allocate.
Oh... I was so focused on figuring out how to wrap a native reference (or, as it
turns out, a native pointer) in a managed wrapper that I missed the fact that
the solution was really intended to solve other problems as well, and, as such,
has implicit usage restrictions placed on it.

Thanks a million Charles and Jeroen!

Bob
Jun 27 '08 #9
"Charles Wang [MSFT]" wrote:
Hi Bob,
Your analysis is correct. The problem here is that the native type
object "myClass" is passed as a parameter to BeginInvoke. There are
two ways to work around this issue, one is changing your MyClass type
from native to managed, and the other one is using a wrapper managed
class to wrap your native type object. For example:
In case writing a new ref class is overkill, consider just using
System::IntPtr.
Jul 29 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
6633
by: Grandma Wilkerson | last post by:
My question concerns the documentation for Control.BeginInvoke(). At one point is says: "Executes the specified delegate asynchronously with the specified arguments, on the thread that the control's underlying handle was created on." later in that same documentation page it says... "Note The BeginInvoke method calls the specified delegate back on a
2
2697
by: Sandor Heese | last post by:
Question, When using BeginInvoke (on a From to marshal to the UI thread) with the EventHandler delegate I see some strange behaviour. The problem is that I call the UpdateTextBox method with a class derived from EventArgs ( i.e. MyEventArgs) and when the BeginInvoke is called and the UpdateTextBox methode is call on the UI thread the parameter e (EventArgs) does not contain the derived MyEventArgs object but a EventArgs object. The...
6
5589
by: arkam | last post by:
Hi, I found a sample on internet : formMain.BeginInvoke(new MyClickHandler(this.OnMyClick)); I would like to do the same but in a class library where there is no forms ! Where can I find a BeginInvoke equivalent for a class library ?
4
2373
by: Jon | last post by:
Why are out parmeters included in an BeginInvoke? They seem to do nothing? TestProgam: using System; namespace TempConsole { class App { public delegate void MyDelegate( out byte b, out string s );
6
15159
by: Valerie Hough | last post by:
I'm not entirely sure what the difference is between these two approaches. In order to avoid reentrant code, I was using Control.BeginInvoke in my UI to cause an asynchronous activity to be done on the UI's message loop. I began to get System.ExecutionEngineException errors so (on the theory of do something different if what you're doing isn't working) I switched to using delegate.BeginInvoke with the appropriate EndInvoke and the problem...
9
5669
by: john doe | last post by:
I have a question about BeginInvoke method found on the Control class. To quote the docs: "Executes the specified delegate asynchronously with the specified arguments, on the thread that the control's underlying handle was created on." Which is fine, but I'm wondering how does this method get called asynchronously if it's on the same thread we are working on? Surely it blocks the thread until returned?
11
9422
by: Dean Shimic | last post by:
void DisplayLines(object state) { for (int i = 0; i < 500; ++i) { int iCopy = i; rtb.BeginInvoke((MethodInvoker)delegate { rtb.AppendText(iCopy + "\n"); }); }
2
3814
by: Flack | last post by:
Hello, If I understand BeginInvoke correctly, when it is called your delegate is run on a thread pool thread. Now, if you supplied a callback delegate, that too is called on the same thread pool thread. My question is this: Do I ever need to check the value of InvokeRequired in my callback method before working with some GUI controls? Won't it always be required since the callback is running on a thread pool thread? I see some code...
10
1910
by: kimiraikkonen | last post by:
Hi, I have a small app which sends using .NET's SmtpClient Class and sends well. But the problem is that i placed a marquee-type progress bar to have an animation and hide by default. Then i placed "progressbar1.show" code inside send button, but the problem is that progress bar is shown after the mail is sent / after operation ends. I want my form displays progress bar at the same time with mail is being sent.
7
5676
by: Ben Voigt [C++ MVP] | last post by:
As much as the CLR team assures us that it's ok to fire-and-forget Control.BeginInvoke, it seems it isn't. Maybe this is a bug. See for example: the comments in http://blogs.msdn.com/cbrumme/archive/2003/05/06/51385.aspx I was encountering a bug that disappeared when debugging. Not when a debugger is attached, mind you, but when I placed a breakpoint near the code. Adding Trace.WriteLine statements showed that the failing code was...
0
9497
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10363
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10169
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9964
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7517
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6749
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5398
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
3670
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2894
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.