Devo passare un callback gestito a un ricevitore TCP non gestito. Poiché è un thread che deve esistere per tutta la durata dell'applicazione, è necessario impedirgli di ottenere i dati raccolti. Ho letto ovunque che i puntatori di funzione di pinning non sono richiesti e GCHandle.Alloc farà il lavoro di prevenzione della garbage collection.Pin un puntatore di funzione
Ma è un dato? Ho visto che l'AppPool che ospita questo codice si arresta in modo anomalo con una violazione di accesso. Perché non dovrei sospettare il fatto che questo errore si verifica perché il puntatore della funzione è stato garbage collocato?
Questo post supporta questo fatto.
Aggiornamento: Questo sembra aver ridotto notevolmente i crash. C'è un problema con questo approccio?
typedef void (__cdecl *ProcMessageFunc)(void* param, void* paramBuf, ULONG bufSize);
FuncDelegate^ fp = gcnew MessageFuncDelegate(this, &Handler);
pin_ptr<MessageFuncDelegate^> pinnedFunctionPointer = &fp;
ret = Receiver ((ProcMessageFunc)pinnedFunctionPointer);
È sufficiente memorizzare l'oggetto delegato in una variabile statica. Il codice nativo può bombardare con violazioni di accesso per molti altri motivi. –
Ho fatto esattamente questo. Il motivo per cui tendo a sospettare che la garbage collection sia la causa è che la violazione di accesso si verifica in modo errato. E, ancora più importante, lo stack di chiamate nel crash dump posso vedere la dll nativa seguita dal clr.dll e quindi dal kernel32.dll in cima allo stack. Questo ordine è coerente. – Krishter