Megosztás a következőn keresztül:


callbackOnCollectedDelegate MDA

Feljegyzés

Ez a cikk a .NET-keretrendszer vonatkozik. Ez nem vonatkozik a .NET újabb implementációira, beleértve a .NET 6-os és újabb verzióit.

A callbackOnCollectedDelegate felügyelt hibakeresési segéd (MDA) akkor aktiválódik, ha egy meghatalmazottat felügyelt kódból nem felügyelt kódba rendeznek függvénymutatóként, és a delegált szemétgyűjtés után visszahívást helyez a függvénymutatóra.

Hibajelenségek

Hozzáférés-megsértések akkor fordulnak elő, ha felügyelt meghatalmazottaktól kapott függvénymutatókon keresztül próbálnak betárcsázást végezni a felügyelt kódba. Ezek a hibák, bár nem gyakori nyelvi futtatókörnyezeti (CLR-) hibák, úgy tűnhetnek, hogy ennek az az oka, hogy a hozzáférés megsértése a CLR-kódban történik.

A hiba nem konzisztens; néha a függvénymutató hívása sikeres, és néha meghiúsul. A hiba csak nagy terhelés vagy véletlenszerűen végrehajtott kísérletek esetén fordulhat elő.

Ok

Az a delegált, amelyből a függvénymutató létre lett hozva, és nem felügyelt kódnak lett kitéve, szemét lett gyűjtve. Amikor a nem felügyelt összetevő megpróbálja meghívni a függvénymutatót, hozzáférési szabálysértést okoz.

A hiba véletlenszerűen jelenik meg, mert a szemétgyűjtés időpontjától függ. Ha egy meghatalmazott jogosult a begyűjtésre, a szemétgyűjtés a visszahívás és a hívás sikeres végrehajtása után is megtörténhet. Máskor a szemétgyűjtés a visszahívás előtt történik, a visszahívás hozzáférési szabálysértést okoz, és a program leáll.

A hiba valószínűsége függ a meghatalmazott és a függvénymutató visszahívása közötti időtől, valamint a szemétgyűjtés gyakoriságától. A hiba szórványos, ha a meghatalmazott és az azt követő visszahívás közötti idő rövid. Ez általában akkor fordul elő, ha a függvénymutatót fogadó nem felügyelt metódus nem menti a függvénymutatót későbbi használatra, hanem a visszatérés előtt azonnal visszahívja a függvénymutatót a művelet befejezéséhez. Hasonlóképpen, több szemétgyűjtés történik, ha egy rendszer nagy terhelés alatt áll, ami nagyobb valószínűséggel fordul elő, hogy a visszahívás előtt szemétgyűjtés történik.

Resolution (Osztás)

Ha egy meghatalmazottat nem felügyelt függvénymutatóként hoztak létre, a szemétgyűjtő nem tudja nyomon követni az élettartamát. Ehelyett a kódnak a nem felügyelt függvénymutató élettartamára kell hivatkoznia a meghatalmazottra. Mielőtt azonban ezt elvégezheti, először meg kell határoznia, hogy melyik meghatalmazottat gyűjtötte össze. Az MDA aktiválása után megadja a meghatalmazott típusnevét. Ezzel a névvel kereshet a kódban olyan platformhívások vagy COM-aláírások kereséséhez, amelyek átadják a nem felügyelt kódnak delegált kódot. A jogsértő meghatalmazott az egyik ilyen híváswebhelyen keresztül kerül átadásra. Azt is engedélyezheti, hogy az gcUnmanagedToManaged MDA minden visszahívás előtt kényszerítse a szemétgyűjtést a futtatókörnyezetbe. Ez megszünteti a szemétgyűjtés által bevezetett bizonytalanságot, és biztosítja, hogy a szemétgyűjtés mindig a visszahívás előtt történjen. Ha már tudja, hogy milyen delegált lett összegyűjtve, módosítsa a kódot, hogy a felügyelt oldalon maradjon a meghatalmazottra mutató hivatkozás a nem felügyelt függvénymutató élettartamára vonatkozóan.

Effektus a futtatókörnyezetre

Ha a meghatalmazottak függvénymutatókként vannak rendezve, a futtatókörnyezet egy olyan osztást foglal le, amely elvégzi a nem felügyeltről a felügyeltre való áttérést. Ez az, amit a nem felügyelt kód hív meg, mielőtt a felügyelt meghatalmazottat végül meghívják. callbackOnCollectedDelegate Az MDA engedélyezése nélkül a nem felügyelt rendezési kód törlődik a meghatalmazott összegyűjtésekor. Ha az callbackOnCollectedDelegate MDA engedélyezve van, a nem felügyelt rendezési kód nem törlődik azonnal a meghatalmazott összegyűjtésekor. Ehelyett az utolsó 1000 példány alapértelmezés szerint életben marad, és úgy változik, hogy híváskor aktiválja az MDA-t. A rendszer végül 1001 további meghatalmazott összegyűjtése után törli a rendszer.

Hozam

Az MDA jelenti annak a meghatalmazottnak a típusnevét, amelyet azelőtt gyűjtöttek össze, hogy visszahívást kíséreltek meg a nem felügyelt függvénymutatóján.

Konfiguráció

Az alábbi példa az alkalmazáskonfigurációs beállításokat mutatja be. 1500-ra állítja az MDA által életben lévő thunkok számát. Az alapértelmezett listSize érték 1000, a minimum 50, a maximum pedig 2000.

<mdaConfig>
  <assistants>
    <callbackOnCollectedDelegate listSize="1500" />
  </assistants>
</mdaConfig>

Példa

Az alábbi példa egy olyan helyzetet mutat be, amely aktiválhatja ezt az MDA-t:

// Library.cpp : Defines the unmanaged entry point for the DLL application.
#include "windows.h"
#include "stdio.h"

void (__stdcall *g_pfTarget)();

void __stdcall Initialize(void __stdcall pfTarget())
{
    g_pfTarget = pfTarget;
}

void __stdcall Callback()
{
    g_pfTarget();
}
// C# Client
using System;
using System.Runtime.InteropServices;

public class Entry
{
    public delegate void DCallback();

    public static void Main()
    {
        new Entry();
        Initialize(Target);
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Callback();
    }

    public static void Target()
    {
    }

    [DllImport("Library", CallingConvention = CallingConvention.StdCall)]
    public static extern void Initialize(DCallback pfDelegate);

    [DllImport ("Library", CallingConvention = CallingConvention.StdCall)]
    public static extern void Callback();

    ~Entry() { Console.Error.WriteLine("Entry Collected"); }
}

Lásd még