Nếu bạn muốn mở ứng dụng của mình, bạn phải làm một cái gì đó để giữ cho quá trình của nó tồn tại. Ví dụ dưới đây là ví dụ đơn giản nhất, được đặt ở cuối chương trình của bạn:
while (true) ;
Tuy nhiên, nó sẽ khiến CPU bị quá tải, do đó nó buộc phải lặp đi lặp lại vô hạn.
Tại thời điểm này, bạn có thể chọn sử dụng System.Windows.Forms.Application
lớp (nhưng nó yêu cầu bạn thêm System.Windows.Forms
tham chiếu):
Application.Run();
Điều này không rò rỉ CPU và hoạt động thành công.
Để tránh thêm System.Windows.Forms
tham chiếu, bạn có thể sử dụng một mẹo đơn giản, cái gọi là chờ đợi , nhập System.Threading
:
SpinWait.SpinUntil(() => false);
Điều này cũng hoạt động hoàn hảo, và về cơ bản nó bao gồm một while
vòng lặp với một điều kiện phủ định được trả về bởi phương thức lambda ở trên. Tại sao CPU này không quá tải? Bạn có thể xem mã nguồn ở đây ; dù sao, về cơ bản, nó chờ một số chu kỳ CPU trước khi lặp lại.
Bạn cũng có thể tạo một looper tin nhắn, trong đó nhìn trộm các tin nhắn đang chờ xử lý từ hệ thống và xử lý từng tin nhắn trước khi chuyển sang lần lặp tiếp theo, như sau:
[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;
}
Sau đó, bạn có thể lặp một cách an toàn bằng cách làm một cái gì đó như thế này:
while (true)
ProcessMessageOnce();