GC.KeepAlive(Object) 方法
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
引用指定的物件,使其從目前例程開始到此方法被呼叫時,無法進行垃圾回收。
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)
參數
- obj
- Object
作為參考的對象。
範例
以下程式碼範例在其方法開始 Main 時建立一個物件,直到最後 KeepAlive 才再次參考該物件,該方法被呼叫。 該物件在方法執行 Main 30 秒期間內持續存在,儘管呼叫了 Collect and WaitForPendingFinalizers 方法。
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
備註
此 KeepAlive 方法的目的是確保存在一個參考,指向一個有被垃圾回收者過早回收風險的物件。 常見的情況是,當受管理程式碼或資料中沒有對該物件的參考,但該物件仍在非受管理程式碼中被使用,例如 Windows API、非受管理 DLL 或使用 COM 的方法。
此方法會參考參數 obj ,使該物件從例程開始到執行順序中不符合垃圾回收資格。 在必須有可用的指令 obj 範圍的最後而非起始處編碼此方法。
此 KeepAlive 方法不執行任何操作,且除了延長作為參數的物件壽命外,沒有產生任何副作用。