GC.KeepAlive(Object) Metódus

Definíció

A megadott objektumra hivatkozik, így nem jogosult a szemétgyűjtésre az aktuális rutin kezdetétől a metódus meghívásának pontig.

public:
 static void KeepAlive(System::Object ^ obj);
public static void KeepAlive(object obj);
public static void KeepAlive(object? obj);
static member KeepAlive : obj -> unit
Public Shared Sub KeepAlive (obj As Object)

Paraméterek

obj
Object

A hivatkozni kívánt objektum.

Példák

Az alábbi példakód egy objektumot hoz létre a metódus elején, és a metódus meghívása Main után KeepAlive nem hivatkozik újra az objektumra. Az objektum a metódus 30 másodperces Main időtartama alatt is megmarad, annak ellenére, hogy meghívja a metódusokat és Collect a WaitForPendingFinalizers metódusokat.

using System;
using System.Threading;
using System.Runtime.InteropServices;

// A simple class that exposes two static Win32 functions.
// One is a delegate type and the other is an enumerated type.
public class MyWin32
{
    // Declare the SetConsoleCtrlHandler function
    // as external and receiving a delegate.
    [DllImport("Kernel32")]
    public static extern Boolean SetConsoleCtrlHandler(HandlerRoutine Handler,
        Boolean Add);

    // A delegate type to be used as the handler routine
    // for SetConsoleCtrlHandler.
    public delegate Boolean HandlerRoutine(CtrlTypes CtrlType);

    // An enumerated type for the control messages
    // sent to the handler routine.
    public enum CtrlTypes
    {
        CTRL_C_EVENT = 0,
        CTRL_BREAK_EVENT,
        CTRL_CLOSE_EVENT,
        CTRL_LOGOFF_EVENT = 5,
        CTRL_SHUTDOWN_EVENT
    }
}

public class MyApp
{
    // A private static handler function in the MyApp class.
    static Boolean Handler(MyWin32.CtrlTypes CtrlType)
    {
        String message = "This message should never be seen!";

        // A switch to handle the event type.
        switch(CtrlType)
        {
            case MyWin32.CtrlTypes.CTRL_C_EVENT:
                message = "A CTRL_C_EVENT was raised by the user.";
                break;
            case MyWin32.CtrlTypes.CTRL_BREAK_EVENT:
                message = "A CTRL_BREAK_EVENT was raised by the user.";
                break;
            case MyWin32.CtrlTypes.CTRL_CLOSE_EVENT:
                message = "A CTRL_CLOSE_EVENT was raised by the user.";
                break;
            case MyWin32.CtrlTypes.CTRL_LOGOFF_EVENT:
                message = "A CTRL_LOGOFF_EVENT was raised by the user.";
                break;
            case MyWin32.CtrlTypes.CTRL_SHUTDOWN_EVENT:
                message = "A CTRL_SHUTDOWN_EVENT was raised by the user.";
                break;
        }

        // Use interop to display a message for the type of event.
        Console.WriteLine(message);

        return true;
    }

    public static void Main()
    {

        // Use interop to set a console control handler.
        MyWin32.HandlerRoutine hr = new MyWin32.HandlerRoutine(Handler);
        MyWin32.SetConsoleCtrlHandler(hr, true);

        // Give the user some time to raise a few events.
        Console.WriteLine("Waiting 30 seconds for console ctrl events...");

        // The object hr is not referred to again.
        // The garbage collector can detect that the object has no
        // more managed references and might clean it up here while
        // the unmanaged SetConsoleCtrlHandler method is still using it.
        
        // Force a garbage collection to demonstrate how the hr
        // object will be handled.
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        
        Thread.Sleep(30000);

        // Display a message to the console when the unmanaged method
        // has finished its work.
        Console.WriteLine("Finished!");

        // Call GC.KeepAlive(hr) at this point to maintain a reference to hr.
        // This will prevent the garbage collector from collecting the
        // object during the execution of the SetConsoleCtrlHandler method.
        GC.KeepAlive(hr);
        Console.Read();
    }
}
open System
open System.Threading
open System.Runtime.InteropServices

// A simple module that exposes two static Win32 functions.
// One is a delegate type and the other is an enumerated type.
module MyWin32 =
    // An enumerated type for the control messages
    // sent to the handler routine.
    type CtrlTypes =
        | CTRL_C_EVENT = 0
        | CTRL_BREAK_EVENT = 1
        | CTRL_CLOSE_EVENT = 2
        | CTRL_LOGOFF_EVENT = 5
        | CTRL_SHUTDOWN_EVENT = 6

    // A delegate type to be used as the handler routine for SetConsoleCtrlHandler.
    type HandlerRoutine = delegate of CtrlTypes -> bool

    // Declare the SetConsoleCtrlHandler function
    // as external and receiving a delegate.
    [<DllImport "Kernel32">]
    extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add)

// A private static handler function in the MyApp class.
let handler (ctrlType: MyWin32.CtrlTypes) =
    let message =
        // Pattern match to handle the event type.
        match ctrlType with
        | MyWin32.CtrlTypes.CTRL_C_EVENT ->
            "A CTRL_C_EVENT was raised by the user."
        | MyWin32.CtrlTypes.CTRL_BREAK_EVENT ->
            "A CTRL_BREAK_EVENT was raised by the user."
        | MyWin32.CtrlTypes.CTRL_CLOSE_EVENT ->
            "A CTRL_CLOSE_EVENT was raised by the user."
        | MyWin32.CtrlTypes.CTRL_LOGOFF_EVENT ->
            "A CTRL_LOGOFF_EVENT was raised by the user."
        | MyWin32.CtrlTypes.CTRL_SHUTDOWN_EVENT ->
            "A CTRL_SHUTDOWN_EVENT was raised by the user."
        | _ -> "This message should never be seen!"

    // Use interop to display a message for the type of event.
    printfn $"{message}"
    true

// Use interop to set a console control handler.
let hr = MyWin32.HandlerRoutine handler
MyWin32.SetConsoleCtrlHandler(hr, true) |> ignore

// Give the user some time to raise a few events.
printfn "Waiting 30 seconds for console ctrl events..."

// The object hr is not referred to again.
// The garbage collector can detect that the object has no
// more managed references and might clean it up here while
// the unmanaged SetConsoleCtrlHandler method is still using it.

// Force a garbage collection to demonstrate how the hr
// object will be handled.
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()

Thread.Sleep 30000

// Display a message to the console when the unmanaged method
// has finished its work.
printfn "Finished!"

// Call GC.KeepAlive(hr) at this point to maintain a reference to hr.
// This will prevent the garbage collector from collecting the
// object during the execution of the SetConsoleCtrlHandler method.
GC.KeepAlive hr
Console.Read() |> ignore
Imports System.Threading
Imports System.Runtime.InteropServices

' A simple class that exposes two static Win32 functions.
' One is a delegate type and the other is an enumerated type.

Public Class MyWin32

   ' Declare the SetConsoleCtrlHandler function as external 
   ' and receiving a delegate.   
   <DllImport("Kernel32")> _
   Public Shared Function SetConsoleCtrlHandler(ByVal Handler As HandlerRoutine, _
         ByVal Add As Boolean) As Boolean
   End Function


   ' A delegate type to be used as the handler routine 
   ' for SetConsoleCtrlHandler.
   Delegate Function HandlerRoutine(ByVal CtrlType As CtrlTypes) As [Boolean]

   ' An enumerated type for the control messages 
   ' sent to the handler routine.

   Public Enum CtrlTypes
      CTRL_C_EVENT = 0
      CTRL_BREAK_EVENT
      CTRL_CLOSE_EVENT
      CTRL_LOGOFF_EVENT = 5
      CTRL_SHUTDOWN_EVENT
   End Enum
End Class

Public Class MyApp

   ' A private static handler function in the MyApp class.
   Shared Function Handler(ByVal CtrlType As MyWin32.CtrlTypes) As [Boolean]
      Dim message As [String] = "This message should never be seen!"

      ' A select case to handle the event type.
      Select Case CtrlType
         Case MyWin32.CtrlTypes.CTRL_C_EVENT
            message = "A CTRL_C_EVENT was raised by the user."
         Case MyWin32.CtrlTypes.CTRL_BREAK_EVENT
            message = "A CTRL_BREAK_EVENT was raised by the user."
         Case MyWin32.CtrlTypes.CTRL_CLOSE_EVENT
            message = "A CTRL_CLOSE_EVENT was raised by the user."
         Case MyWin32.CtrlTypes.CTRL_LOGOFF_EVENT
            message = "A CTRL_LOGOFF_EVENT was raised by the user."
         Case MyWin32.CtrlTypes.CTRL_SHUTDOWN_EVENT
            message = "A CTRL_SHUTDOWN_EVENT was raised by the user."
      End Select

      ' Use interop to display a message for the type of event.
      Console.WriteLine(message)

      Return True
   End Function


   Public Shared Sub Main()
      ' Use interop to set a console control handler.
      Dim hr As New MyWin32.HandlerRoutine(AddressOf Handler)
      MyWin32.SetConsoleCtrlHandler(hr, True)

      ' Give the user some time to raise a few events.
      Console.WriteLine("Waiting 30 seconds for console ctrl events...")

      ' The object hr is not referred to again.
      ' The garbage collector can detect that the object has no
      ' more managed references and might clean it up here while
      ' the unmanaged SetConsoleCtrlHandler method is still using it.      
      ' Force a garbage collection to demonstrate how the hr
      ' object will be handled.
      GC.Collect()
      GC.WaitForPendingFinalizers()
      GC.Collect()

      Thread.Sleep(30000)

      ' Display a message to the console when the unmanaged method
      ' has finished its work.
      Console.WriteLine("Finished!")

      ' Call GC.KeepAlive(hr) at this point to maintain a reference to hr. 
      ' This will prevent the garbage collector from collecting the 
      ' object during the execution of the SetConsoleCtrlHandler method.
      GC.KeepAlive(hr)
      Console.Read()
   End Sub
End Class

Megjegyzések

A módszer célja KeepAlive annak biztosítása, hogy létezik-e olyan tárgyra mutató hivatkozás, amelyet a szemétgyűjtő idő előtt visszanyer. Ez általában akkor fordulhat elő, ha a felügyelt kódban vagy adatokban nincs hivatkozás az objektumra, de az objektum továbbra is használatban van nem felügyelt kódban, például Windows API-kban, nem felügyelt DLL-ekben vagy COM-t használó metódusokban.

Ez a metódus a obj paraméterre hivatkozik, így az objektum nem jogosult a szemétgyűjtésre a rutin elejétől a végrehajtási sorrendig, ahol ezt a metódust meghívják. Kódozza ezt a metódust annak az utasítástartománynak a végén, nem pedig az elején, ahol obj elérhetőnek kell lennie.

A KeepAlive metódus nem végez műveletet, és nem okoz más mellékhatást, mint a paraméterként átadott objektum élettartamának meghosszabbítása.

A következőre érvényes: