Jeśli chcesz, aby Twoja aplikacja pozostała otwarta, musisz coś zrobić, aby utrzymać jej proces. Poniższy przykład jest najprostszym przykładem, który należy umieścić na końcu programu:
while (true) ;
Jednak spowoduje to przeciążenie procesora, ponieważ w związku z tym jest zmuszony do nieskończonej iteracji.
W tym momencie możesz zdecydować się na użycie System.Windows.Forms.Application
klasy (ale wymaga to dodania System.Windows.Forms
referencji):
Application.Run();
To nie powoduje wycieku procesora i działa pomyślnie.
Aby uniknąć dodawania System.Windows.Forms
referencji, możesz skorzystać z prostego triku, tzw. Czekania spinowego , importującego System.Threading
:
SpinWait.SpinUntil(() => false);
Działa to również doskonale i zasadniczo składa się z while
pętli z zanegowanym warunkiem, który jest zwracany przez powyższą metodę lambda. Dlaczego to nie przeciąża procesora? Możesz spojrzeć na kod źródłowy tutaj ; w każdym razie po prostu czeka jakiś cykl procesora przed iteracją.
Możesz także utworzyć pętlę komunikatów, która przegląda oczekujące wiadomości z systemu i przetwarza każdą z nich przed przejściem do następnej iteracji, w następujący sposób:
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "PeekMessage")]
public static extern int PeekMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, int wMsgFilterMax, int wRemoveMsg);
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "GetMessage")]
public static extern int GetMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, int wMsgFilterMax);
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "TranslateMessage")]
public static extern int TranslateMessage(ref NativeMessage lpMsg);
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "DispatchMessage")]
public static extern int DispatchMessage(ref NativeMessage lpMsg);
[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode]
public static bool ProcessMessageOnce()
{
NativeMessage message = new NativeMessage();
if (!IsMessagePending(out message))
return true;
if (GetMessage(out message, IntPtr.Zero, 0, 0) == -1)
return true;
Message frameworkMessage = new Message()
{
HWnd = message.handle,
LParam = message.lParam,
WParam = message.wParam,
Msg = (int)message.msg
};
if (Application.FilterMessage(ref frameworkMessage))
return true;
TranslateMessage(ref message);
DispatchMessage(ref message);
return false;
}
Następnie możesz bezpiecznie zapętlić, wykonując coś takiego:
while (true)
ProcessMessageOnce();