473,320 Members | 1,870 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

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 14482
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
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
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
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
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
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
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
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
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
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
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

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.