C #, обеспечивающий обратные вызовы C ++, нарушение прав доступа в _threadex.c в endthread () - PullRequest
1 голос
/ 17 мая 2009

У меня есть приложение-служба C # Windows, которое передает указатель на функцию обратного вызова в dll C ++. Я определил как указатель функции на стороне C #, так и на стороне C ++ для типа __stdcall. Все работает нормально до тех пор, пока Cll не вызовет обратный вызов и не выдаст необработанное нарушение доступа к исключениям в 0x04cb0e. Отладка останавливается в файле treadex.c под вызовом endthread в приложении C #.

public delegate void NotificationFunc(int notifycode, IntPtr Userdata);

[DllImport("notice.dll")]
void INotify(NotificationFunc notefunc,IntPtr Userdata);//ignore the IntPtr Userdata
.
.
.
NotificationFunc notefunc = new NotificationFunc(Noticallback);
INotify(notefunc, Intptr.zero);

//notice.dll triggers this callback thru the delegate passed in
void Noticallback(int notifycode, IntPtr userdata)
{
Swtich(notifycode)
{
//my actions
}
.
.//Error Exceptions happens here when trying to end the thread/call
}

Я знаю, что должен обработать ресурсы обратного вызова, так как это событие одностороннего вызова. Я пробовал GC & GCHandle, чтобы он не был GC, но кажется, что всегда есть утечка памяти или ошибка. Может кто-нибудь помочь? Спасибо

Ответы [ 2 ]

1 голос
/ 17 мая 2009

Необходимо запретить сбор делегата управляемым кодом, используя GCHandle.Alloc:

    public delegate void NotificationFunc(int notifycode, IntPtr Userdata);

    [DllImport("notice.dll")]
    static extern void INotify(NotificationFunc notefunc,IntPtr Userdata); // Note IntPtr as the callback type


    NotificationFunc notefunc = new NotificationFunc(Noticallback);

    // Now, allocate a GCHandle to prevent the delegate from being collected
    GCHandle handle = GCHandle.Alloc(notefunc);

    INotify(notefunc, Intptr.Zero);

    // Free the handle when it's no longer needed
    handle.Free();
1 голос
/ 17 мая 2009

Википедия имеет довольно приличную статью на эту тему. На вашем месте я бы использовал C ++ / CLI, так как он быстрее и не так сильно связан. Этот тип P / Invoke, где вы размещаете все определения повсеместно, очень подвержен ошибкам. И если вы когда-либо измените или если спецификация изменится на вас, для ваших типов данных или чего-то в этом роде, C ++ / CLI будет автоматически обновляться, но, к сожалению, любые явные изменения P / Invoke, как у вас здесь, всегда будут -wired.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...