>>> Hi,
>>>
>>> Thanks for your message, but I am still getting the Application to crash
>>> if I am calling the Asynchronous Methods. I said before that When I am
>>> calling unmanaged code asynchronous methods in C# it causes an error, if
>>> I call the exact parameters for the synchronous method, it works fine.
>>> Cause there is an unmanaged thread within the unmanaged method.
>>>
>>> I was doing as you mentioned and still getting Application Crash:
>>>
>>> // Start scheduler
>>> HD.hdlStart();
>>>
>>> SchedulerCallback cb = new
>>> SchedulerCallback(HapticCallback);
>>>
>>> uint temp = deviceAsynchronous(cb, (IntPtr)0, 1);
>>>
>>> GC.KeepAlive(call);
>>>
>>>
>>> It crashes right after the first iteration of the calback, so when I
>>> trigger deviceAsynchronous it creates an infinite loop that I can get
>>> data from. But it still seems that It isn't working
>>>
>>> Any more ideas what I have done wrong?
>>
>> The KeepAlive method should have the delegate reference as argument, not
>> sure whether "call" is a typo but it should be "cb".
>>
>> uint temp = deviceAsynchronous(cb, (IntPtr)0, 1);
>> GC.KeepAlive(call);
>>
>> should be:
>>
>> uint temp = deviceAsynchronous(cb, (IntPtr)0, 1);
>> GC.KeepAlive(cb);
>>
>> Also you need to keep the delegate alive for as long as you can get
>> called back from the unmanaged thread. In above snippet, you are only
>> keeping the delegate alive for the duration of the call into unmanaged,
>> but not any longer (which makes no sense as this is done automatically by
>> the interop layer)! That means that when the unmanaged thread calls you
>> back after KeepAlive(), the call may fail because the delegate might be
>> collected. So it's up to you put the KeepALive call there where you are
>> sure you won't get called back any longer.
>>
>> Willy.
>>
It makes no sense to put the GC.KeepAlive rigt behind the unmanaged function
call, this won't protect the delegate from being collected, you need to put
the GC.KeepAlive call at the point you are sure the delegate won't get
called back any longer! Be carefull where you declare the delegate, if you
need the delegate to be kept alive for the duration of the program
(AppDomain to be exact) you will have to declare it as static, in that case
you won't need the KeepAlive call as statics have the same lifetime as the
AD they are "part of".
Herewith a small sample illustrating the above, compile both as-is and run
the program, you'll see it works.
Now remove the KeepAlive(or put it right behaind the unmanaged function call
and it will fail.
// C# Test.cs
using System;
using System.Runtime.InteropServices;
using System.Security;
class Program
{
delegate void MyDelegate(int arg);
void MyCallBack(int arg)
{
Console.Write(arg);
}
static void Main()
//
{
Program t = new Program();
MyDelegate del = new MyDelegate(t.MyCallBack);
UnmanagedFunc(del);
GC.Collect();
Console.ReadLine();
GC.KeepAlive(del);
}
[DllImport("MyClib"), SuppressUnmanagedCodeSecurity]
static extern void UnmanagedFunc(MyDelegate f);
}
// C File
// Compile using: cl /LD /O2 MyClib.cpp
#include <windows.h>
typedef void (__stdcall *UnmCallBack)(DWORD b);
DWORD WINAPI ThreadFunc1( PVOID p ) {
for(int i = 0; i < 10; i++)
{
UnmCallBack f = static_cast<UnmCallBack>(p);
f(i);
Sleep(500);
}
return 0;
}
extern "C" void __declspec(dllexport) __stdcall
UnmanagedFunc(PVOID/*LPTHREAD_START_ROUTINE*/ cb)
{
DWORD id = 0;
CreateThread(NULL, 0, ThreadFunc1, (PVOID)cb, 0, &id);
}