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 ,不會再次參考物件。 物件會保存方法的 30 秒持續時間 Main
,即使呼叫 Collect 和 WaitForPendingFinalizers 方法。
using namespace System;
using namespace System::Threading;
using namespace 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 ref class MyWin32
{
public:
// An enumerated type for the control messages sent to the handler routine.
enum class CtrlTypes
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
};
delegate Boolean HandlerRoutine( // A delegate type to be used as the Handler Routine for SetConsoleCtrlHandler.
CtrlTypes CtrlType );
// Declare the SetConsoleCtrlHandler function as external and receiving a delegate.
[DllImport("Kernel32")]
static Boolean SetConsoleCtrlHandler( HandlerRoutine^ Handler, Boolean Add );
};
public ref class MyApp
{
private:
// 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 Test()
{
// Use interop to set a console control handler.
MyWin32::HandlerRoutine^ hr = gcnew 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 );
}
};
int main()
{
MyApp::Test();
}
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 要確保垃圾收集行程提前回收物件的參考是否存在。 當 Managed 程式碼或資料中沒有物件參考,但物件仍在非受控程式碼中使用,例如 Windows API、Unmanaged DLL 或使用 COM 的方法時,可能會發生這種情況。
這個方法會參考 obj
參數,讓該物件無法從常式的開頭到呼叫此方法的執行順序中的垃圾收集。 在結尾撰寫這個方法的程式碼,而不是必須提供之指示 obj
範圍的開頭。
方法 KeepAlive 不會執行任何作業,而且除了擴充傳入做為參數的物件存留期以外,不會產生副作用。