473,480 Members | 1,872 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

callback on a garbage collected delegate error

Hi,

I have an application using a DLL and callbacks. It generate random the
error "A callback was made on a garbage collected delegate".

I found some articles that the pointer to the delegate has to have a
lifetime reference so that it is not garbage collected. But I could not find
any example how to do this.

Can someone help here ?

--
rgds, Wilfried
http://www.mestdagh.biz
Sep 25 '06 #1
13 14517
Wilfried,

Just assign the delegate reference to a field in a class that has the
same lifetime as the callback. So if you have a class instance which will
receive the callback, then assign the delegate to a field on the class.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Wilfried Mestdagh" <Wi**************@discussions.microsoft.comwrote in
message news:8A**********************************@microsof t.com...
Hi,

I have an application using a DLL and callbacks. It generate random the
error "A callback was made on a garbage collected delegate".

I found some articles that the pointer to the delegate has to have a
lifetime reference so that it is not garbage collected. But I could not
find
any example how to do this.

Can someone help here ?

--
rgds, Wilfried
http://www.mestdagh.biz

Sep 25 '06 #2
Hi,

I understeand but I dont understeand how and where.

I have following:

public class Api
{
public Api(Control control)
{
owner = control;
ApiDll.Start();
ApiDll.SetLoggedOn(cbLoggedOn);
// cb... is a callback function in this class
// Set LoggedOn is the procedure to place the pointer in the DLL
// etc...

Then in main form:

public partial class Main : Form
{
private Api api;

public Main()
{
InitializeComponent();
api = new Api(this);
api.OnLoggedOn += api_OnLoggedOn;
// etc..

then in the DLL declaration:

public static class ApiDll
{
private const string dllName = "SmsComfortAPI.dll";

public delegate void OnLoggedOn();
// etc...

[DllImport(dllName)]
public static extern void SetLoggedOn(OnLoggedOn cbLoggedOn);
// etc...
Where and how should I declare the lifetime inctance ?

--
rgds, Wilfried
http://www.mestdagh.biz
Sep 25 '06 #3
Wilfried,

Where are you getting cb from? If it is a member in your Api class,
then the problem is that the class is being collected (not just the
delegate).

You need to call a function to unregister the callback so that it
doesn't try and call your function back. Either that, or you need to have a
static method and pass a delegate to that, and then register with the class
for the callback.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Wilfried Mestdagh" <Wi**************@discussions.microsoft.comwrote in
message news:A0**********************************@microsof t.com...
Hi,

I understeand but I dont understeand how and where.

I have following:

public class Api
{
public Api(Control control)
{
owner = control;
ApiDll.Start();
ApiDll.SetLoggedOn(cbLoggedOn);
// cb... is a callback function in this class
// Set LoggedOn is the procedure to place the pointer in the
DLL
// etc...

Then in main form:

public partial class Main : Form
{
private Api api;

public Main()
{
InitializeComponent();
api = new Api(this);
api.OnLoggedOn += api_OnLoggedOn;
// etc..

then in the DLL declaration:

public static class ApiDll
{
private const string dllName = "SmsComfortAPI.dll";

public delegate void OnLoggedOn();
// etc...

[DllImport(dllName)]
public static extern void SetLoggedOn(OnLoggedOn cbLoggedOn);
// etc...
Where and how should I declare the lifetime inctance ?

--
rgds, Wilfried
http://www.mestdagh.biz

Sep 25 '06 #4
Hi Nicholas,
Where are you getting cb from? If it is a member in your Api class,
then the problem is that the class is being collected (not just the
delegate).
the cb... functions are indeed a members of the Api class.
You need to call a function to unregister the callback so that it
doesn't try and call your function back. Either that, or you need to have a
static method and pass a delegate to that, and then register with the class
for the callback.
I dont understeand. English is not my native language eather. How do I make
a function to uregister it ? But if it is unregistered then how will the
callback works ?

The project load a DLL. DLL communicate with a server trough a TCP session.
The callback is needed to get data from server. So I dont understeand the
unregistering...

Should I make a simple project to demonstrate and publish it for download ?

--
rgds, Wilfried
http://www.mestdagh.biz
Sep 25 '06 #5
Wilifried,

You have an API function SetLoggedOn, then it is storing in that dll the
address of the callback function. When someone logs on, it is calling the
callback function.

You have to tell it to stop calling that callback, since your instance
goes out of scope.

What I think you should do is make this event static, and then make your
delegate to a static method.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
"Wilfried Mestdagh" <Wi**************@discussions.microsoft.comwrote in
message news:40**********************************@microsof t.com...
Hi Nicholas,
> Where are you getting cb from? If it is a member in your Api class,
then the problem is that the class is being collected (not just the
delegate).

the cb... functions are indeed a members of the Api class.
> You need to call a function to unregister the callback so that it
doesn't try and call your function back. Either that, or you need to
have a
static method and pass a delegate to that, and then register with the
class
for the callback.

I dont understeand. English is not my native language eather. How do I
make
a function to uregister it ? But if it is unregistered then how will the
callback works ?

The project load a DLL. DLL communicate with a server trough a TCP
session.
The callback is needed to get data from server. So I dont understeand the
unregistering...

Should I make a simple project to demonstrate and publish it for download
?

--
rgds, Wilfried
http://www.mestdagh.biz

Sep 25 '06 #6
Hi Nicholas,
You have an API function SetLoggedOn, then it is storing in that dll the
address of the callback function. When someone logs on, it is calling the
callback function.
SetLoggedOn installs the callback pointer into the DLL. The DLL calls back
to the pointer when the application is logged on to the server.
You have to tell it to stop calling that callback, since your instance
goes out of scope.
But the DLL needs the callback and other callback for many other events. The
DLL comunicate with a server and data can arrive.
What I think you should do is make this event static, and then make your
delegate to a static method.
I think I tryed already to make the procedure static with same result. But I
tryed in the last hours so many things I'm not sure anymore (including
banging my head on keyboard and monitore)...

--
rgds, Wilfried
http://www.mestdagh.biz
Sep 25 '06 #7

"Wilfried Mestdagh" <Wi**************@discussions.microsoft.comwrote in
message news:87**********************************@microsof t.com...
| Hi Nicholas,
|
| You have an API function SetLoggedOn, then it is storing in that dll
the
| address of the callback function. When someone logs on, it is calling
the
| callback function.
|
| SetLoggedOn installs the callback pointer into the DLL. The DLL calls back
| to the pointer when the application is logged on to the server.
|
| You have to tell it to stop calling that callback, since your
instance
| goes out of scope.
|
| But the DLL needs the callback and other callback for many other events.
The
| DLL comunicate with a server and data can arrive.
|
| What I think you should do is make this event static, and then make
your
| delegate to a static method.
|
| I think I tryed already to make the procedure static with same result. But
I
| tryed in the last hours so many things I'm not sure anymore (including
| banging my head on keyboard and monitore)...
|
| --
| rgds, Wilfried
| http://www.mestdagh.biz

We have to see how and where you create an instance of your delegate, so,
please post a short but complete repro that illustrates your issue.
incomplete code snips like you posted aren't of great help.
Willy.
Sep 25 '06 #8
Hi,

Yes you are right of course. I made a simple application to demonstrate my
problem. It is containing only the nececary. I also made source for download
if that is more easy on http://www.mestdagh.biz/kieken/CrashTest.zip The dll
I made for the demo is just calling the callback with the same data. this is
the complete project. Using the garbage collector I can let it reproduce the
error 1 on 2 times.

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace DllCrashDemo
{
public partial class Form1 : Form
{
private Api api;

public Form1()
{
InitializeComponent();
api = new Api(this);
api.OnShow += api_OnShow;
}

void api_OnShow(object sender, Api.ShowItArgs e)
{
listBox.Items.Add(e.text);
}

private void crashButton_Click(object sender, EventArgs e)
{
api.show("This is a crashtest");
}
}

public class Api
{
private Control owner;

public Api(Control control)
{
owner = control;
ApiDll.SetShow(cbShow);
}

public void show(string text)
{
ApiDll.ShowIt(text);
GC.Collect();
}

public class ShowItArgs : EventArgs
{
public string text;
}
public delegate void Show(object sender, ShowItArgs e);
public event Show OnShow;
private void cbShow(string text)
{
if (OnShow == null)
return;
ShowItArgs e = new ShowItArgs();
e.text = text;
owner.Invoke(OnShow, new object[] { this, e });
}
}

public static class ApiDll
{
private const string crashDllName = @"C:\Program
Files\Borland\Delphi7\Projects\CrashDll.dll";

public delegate void OnShow([MarshalAs(UnmanagedType.LPStr)]string
txt);

[DllImport(crashDllName)]
public static extern void
ShowIt([MarshalAs(UnmanagedType.LPStr)]string txt);
[DllImport(crashDllName)]
public static extern void SetShow(OnShow cbShow);
}
}

--
rgds, Wilfried
http://www.mestdagh.biz
"Willy Denoyette [MVP]" wrote:
>
"Wilfried Mestdagh" <Wi**************@discussions.microsoft.comwrote in
message news:87**********************************@microsof t.com...
| Hi Nicholas,
|
| You have an API function SetLoggedOn, then it is storing in that dll
the
| address of the callback function. When someone logs on, it is calling
the
| callback function.
|
| SetLoggedOn installs the callback pointer into the DLL. The DLL calls back
| to the pointer when the application is logged on to the server.
|
| You have to tell it to stop calling that callback, since your
instance
| goes out of scope.
|
| But the DLL needs the callback and other callback for many other events.
The
| DLL comunicate with a server and data can arrive.
|
| What I think you should do is make this event static, and then make
your
| delegate to a static method.
|
| I think I tryed already to make the procedure static with same result. But
I
| tryed in the last hours so many things I'm not sure anymore (including
| banging my head on keyboard and monitore)...
|
| --
| rgds, Wilfried
| http://www.mestdagh.biz

We have to see how and where you create an instance of your delegate, so,
please post a short but complete repro that illustrates your issue.
incomplete code snips like you posted aren't of great help.
Willy.
Sep 26 '06 #9
Wilfried Mestdagh <Wi**************@discussions.microsoft.comwrote :
Yes you are right of course. I made a simple application to demonstrate my
problem. It is containing only the nececary. I also made source for download
if that is more easy on http://www.mestdagh.biz/kieken/CrashTest.zip The dll
I made for the demo is just calling the callback with the same data. this is
the complete project. Using the garbage collector I can let it reproduce the
error 1 on 2 times.
Ah - I don't know whether it's because I missed something before or
not, but I hadn't realised you were talking about unmanaged code
calling you back. That explains why the garbage collector was able to
collect the delegate in the first place.

There are various ways you could handle this, but the main thing is
that you'll need to keep a reference to the delegate within managed
code.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 26 '06 #10
Hi,

I understeand. Only I'm not sure how to do it. I'm trying to assign a
pointer to the callback method in unsafe code, but I miss the syntax
somewhere I think.

Can you give example ?

--
rgds, Wilfried
http://www.mestdagh.biz
Sep 26 '06 #11
Wilfried Mestdagh <Wi**************@discussions.microsoft.comwrote :
I understeand. Only I'm not sure how to do it. I'm trying to assign a
pointer to the callback method in unsafe code, but I miss the syntax
somewhere I think.

Can you give example ?
Here's one alternative implementation of ApiDll:

public static class ApiDll
{
private const string crashDllName = @"C:\Program
Files\Borland\Delphi7\Projects\CrashDll.dll";

public delegate void OnShow([MarshalAs(UnmanagedType.LPStr)]
string
txt);

private static OnShow showDelegate;

[DllImport(crashDllName)]
public static extern void
ShowIt([MarshalAs(UnmanagedType.LPStr)]string txt);
[DllImport(crashDllName)]
private static extern void SetShow(OnShow cbShow);

public static void SetShowDelegate (OnShow cbShow)
{
showDelegate = cbShow;
SetShow(cbShow);
}
}

Now, that's fine so long as you only ever want one delegate registered
at a time - the static variable will prevent the delegate from being
garbage collected. Are you okay with that limitation?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 26 '06 #12
Hi,

this works great. Thank you :) I was already trying to make a class with a
void* to the callback function but did not found the right syntax. Possible
also a solution?
Now, that's fine so long as you only ever want one delegate registered
at a time - the static variable will prevent the delegate from being
garbage collected. Are you okay with that limitation?
Yes. There are several different callbacks, but each callback will only have
1 and the same callback function during the liftime of the application.

The same limitation is that there only may be 1 incstance of the Api class
right ? Maybe it is better technique to make the Api class also a static
class ?

--
rgds, Wilfried
http://www.mestdagh.biz
Sep 26 '06 #13
Wilfried Mestdagh <Wi**************@discussions.microsoft.comwrote :
this works great. Thank you :) I was already trying to make a class with a
void* to the callback function but did not found the right syntax. Possible
also a solution?
I'm not sure whether you're asking a question there or not (or what it
is if you are). The equivalent to some uses of "void*" in .NET is just
to use "object" - if you want a reference to absolutely anything,
that's the type to use.
Now, that's fine so long as you only ever want one delegate registered
at a time - the static variable will prevent the delegate from being
garbage collected. Are you okay with that limitation?

Yes. There are several different callbacks, but each callback will only have
1 and the same callback function during the liftime of the application.

The same limitation is that there only may be 1 incstance of the Api class
right ? Maybe it is better technique to make the Api class also a static
class ?
It sounds like it, yes. That makes me nervous in terms of OO design,
but I think it's really suggested by the restriction anyway.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 26 '06 #14

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

Similar topics

8
12896
by: Martin Maat | last post by:
I am puzzled. I have this object that uses a thread. The thread is encapsulated by the object, the object has Start and Stop methods to enable the client to start or stop the thread. I found...
4
2378
by: Sai Kit Tong | last post by:
I have to interface managed application with my legacy dll. I have employed the wrapper approach but I have to deal with the asynchronous callback from the legacy dll, which likely goes through a...
9
2178
by: Olivier Fermy | last post by:
I have created a sample project where i have referenced an object only with an event : textBox.VisibleChanged += new EventHandler(this.textBox_VisibleChanged); When i call GC.Collect(), the...
6
2387
by: Minfu Lu | last post by:
I have a problem dealing with passing a function address to a COM callback. I use this COM function for communicating to a hardware. My original project was written in VB. I have converted it to...
4
1970
by: FishingScout | last post by:
I am re-writing an MS VC++ 6.0 application in Visual Studio 2005 VB.NET. In order for my new application to communicate with some hardware (an RFID reader) I need to communicate with a DLL that...
4
1678
by: R. MacDonald | last post by:
Hello, all, I have a .NET application (VB) that passes the address of a delegate to unmanaged code in a DLL. The unmanaged code then uses the delegate as a call-back. This seems to work...
6
14045
by: Bart Burkhardt | last post by:
Hi, I could use some help in setting a C# callback function that an external unmanaged dll will call on a event. Using a delegate and use the external callback set function doesn't work. The...
4
4774
by: Edwin Gomez | last post by:
I'm a C# developer and I'm new to Python. I would like to know if the concept of Asynchronous call-backs exists in Python. Basically what I mean is that I dispatch a thread and when the thread...
10
6920
by: SQACPP | last post by:
Hi, I try to figure out how to use Callback procedure in a C++ form project The following code *work* perfectly on a console project #include "Windows.h" BOOL CALLBACK...
0
7041
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7043
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,...
1
6737
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
6921
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...
1
4776
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...
0
2984
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1300
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
563
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
179
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...

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.