|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Есть DLL на С++, которая создает внутри себя отдельный поток и при некоторых событиях из него вызывает ранее переданную функцию. исходникиНа c# выглядит так Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
В С++ написано так Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8.
Код работает, но периодически происходит вылет с исключением System.AccessViolationException (обращение к несуществующей памяти). Причем никакой почторяемости, может на 2-3 вызов вылететь, может сотню отработать. Вылет в момент вызова, DLL пишет "Run callback.\n" перед вызовом, а до написания "callback ..." не доходит. Я так подозреваю что проблема в вызове Alert() в потоке, о котором C# вообще не знает ничего. Хотел спросить: можно так делать? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2016, 10:55 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Dima T, имхо нужно застолбить указатель myCallBack через unsafe, уборщик может поменять у нее указатель, и тогда действительно с++ можем попасть в просак ... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2016, 11:29 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Где-то в степиимхо нужно застолбить указатель myCallBack через unsafe, уборщик может поменять у нее указатель Тоже об этом подумал. Еще появилась мысль что myCallBack может быть вообще удален сборщиком, т.к. нигде больше не упоминается. Переделал его из локальной переменной в свойство класса. Переделал на такой вариант Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Пока не вылетает, мониторю. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2016, 11:52 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Dima T, да вполне достаточно Код: c# 1. 2. 3. 4. 5. 6. 7. 8.
уборшик не будет анализировать эту область и перемешать в куче ее внутренности внутренности если хотите оперировать указателями в типе можно так Код: c# 1. 2. 3.
... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2016, 12:08 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Dima T, Alert наверное лучше статиком сделать, если нет то не использовать его - а инициализировать по месту объявления в параметрах вызова. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2016, 12:18 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
После исправлений 19588446 не вылетало больше. Пришел к выводу что нездоровую хрень я написал. Тут достаточно взять AutoResetEvent в коде DLL его устанавливать, а в C# висеть в ожидании. И никаких колбэков не надо. Переделаю. Эта dll работает в другой проге, на С++, там так проще было реализовать. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2016, 13:18 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Где-то в степиимхо нужно застолбить указатель myCallBack через unsafeУказатели "столбятся" через fixed . Не надо тут ничего "столбить", механизм PInvoke сам что нужно "застолбит" при необходимости. Нужно просто проверить содержимое "колбэка" на потокобезопасность. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 11:19 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Dima TПосле исправлений 19588446 не вылетало больше.Исправления не внесли никаких изменений. Просто разрешил работу с указателями, которой нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 11:25 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Алексей КDima TПосле исправлений 19588446 не вылетало больше.Исправления не внесли никаких изменений. Просто разрешил работу с указателями, которой нет. Одно было: переделал myCallBack из локальной переменной в свойство класса. Помогло или не очень сложно сказать, после исправления не вылетало, 5 часов проработало, а потом переписал: заменил колбэк на AutoResetEvent. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 11:43 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Dima TАлексей Кпропущено... Исправления не внесли никаких изменений. Просто разрешил работу с указателями, которой нет. Одно было: переделал myCallBack из локальной переменной в свойство класса.Это ничего не меняет. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 11:48 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Алексей КDima Tпропущено... Одно было: переделал myCallBack из локальной переменной в свойство класса.Это ничего не меняет. Меняет. Код: c# 1. 2. 3. 4.
После отработки Init() компилятор считает myCallBack больше не нужным и удаляет при сборке мусора, во внутрь SetFunc() компилятор заглянуть не может, т.к. это С++. У Рихтера есть пример похожей ситуации, когда он создает таймер и больше не упоминает его в коде, и после сборки мусора таймер перестает срабатывать. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 12:01 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Dima TАлексей Кпропущено... Это ничего не меняет. Меняет. Код: c# 1. 2. 3. 4.
После отработки Init() компилятор считает myCallBack больше не нужным и удаляет при сборке мусора, во внутрь SetFunc() компилятор заглянуть не может, т.к. это С++. У Рихтера есть пример похожей ситуации, когда он создает таймер и больше не упоминает его в коде, и после сборки мусора таймер перестает срабатывать.Сборщик мусора удаляет делегат вместе с скомпилированным телом метода, адрес которого передан в неуправляемый C++ код? Мне кажется, что Рихтер не мог написать такого. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 12:08 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Алексей КDima Tпропущено... Меняет. Код: c# 1. 2. 3. 4.
После отработки Init() компилятор считает myCallBack больше не нужным и удаляет при сборке мусора, во внутрь SetFunc() компилятор заглянуть не может, т.к. это С++. У Рихтера есть пример похожей ситуации, когда он создает таймер и больше не упоминает его в коде, и после сборки мусора таймер перестает срабатывать.Сборщик мусора удаляет делегат вместе с скомпилированным телом метода, адрес которого передан в неуправляемый C++ код? Мне кажется, что Рихтер не мог написать такого. Рихтер писал про таймер, а не делегат. В данном случае тоже имеем объект "new CallBack(Alert)". Почему сборщик мусора не должен удалить этот объект? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 12:15 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Алексей Кделегат вместе с скомпилированным телом метода, адрес которого передан в неуправляемый C++ код В С++ попал не адрес тела метода, а какой-то адрес кода-обертки, т.к. C++ понятия не имеет что это метод конкретного объекта, C++ ожидает функцию, т.е. static метод. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 12:21 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Dima T, Сдаётся мне, что через PInvoke есть смысл передавать только делегаты, указывающие на статические методы. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 15:39 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Алексей КDima T, Сдаётся мне, что через PInvoke есть смысл передавать только делегаты, указывающие на статические методы. Почему? Просто вынести myCallBack в свойства объекта где он используется и он будет уничтожен одновременно с объектом, дополнительно прописать в Dispose() Код: c# 1.
чтобы С++ не вызывал несуществующий код. Меня больше напрягает что поток, в котором вызывается Alert() создан в С++ коде SetFunc(), т.е. .Net ничего не знает про него, возможно .Net пишет какую-то инфу в контекст потока, когда сам создает поток, а тут этого нет, как понадобится эта инфа так все и переглючит. Поэтому переделал такC# Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25.
C++ Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9.
Тут если даже hAlert примет несуществующие значение, то никаких вылетов не будет. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 16:14 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Dima TАлексей КDima T, Сдаётся мне, что через PInvoke есть смысл передавать только делегаты, указывающие на статические методы. Почему?Потому что в традиционном неуправляемом коде нет делегатов, есть только указатели на функции, что есть частный случай делегата - делегат статического метода. Не забываем, что делегат - это не просто указатель на функцию, это пара указателей - указатель на функцию и указатель на объект. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 17:27 |
|
Можно делать Callback в потоке, о котором .NET ничего не знает?
|
|||
---|---|---|---|
#18+
Dima T, Хотя нет, Рихтер походу прав . Не знал. авторAlso, make sure the lifetime of the delegate instance covers the lifetime of the unmanaged code; otherwise, the delegate will not be available after it is garbage-collected. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2016, 17:36 |
|
|
start [/forum/topic.php?fid=20&msg=39298470&tid=1400376]: |
0ms |
get settings: |
8ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
50ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
50ms |
get tp. blocked users: |
1ms |
others: | 12ms |
total: | 152ms |
0 / 0 |