Vấn đề
Khởi động một dịch vụ Windows lẽ ra là một quá trình suôn sẻ. Tuy nhiên, các quy trình khởi tạo nặng nề thường kích hoạt hộp thoại Error 1053 gây khó chịu. Điều này thường xảy ra khi một dịch vụ tùy chỉnh mất quá nhiều thời gian để báo cáo trạng thái "Started" trở lại hệ điều hành.
Theo mặc định, Windows Service Control Manager (SCM) rất thiếu kiên nhẫn. Nó cung cấp cho các dịch vụ chính xác 30.000 mili giây (30 giây) để phát tín hiệu rằng chúng đang chạy. Nếu dịch vụ của bạn vẫn đang bận tải các tệp cấu hình lớn hoặc kết nối với cơ sở dữ liệu từ xa khi bộ đếm ngược đó về không, Windows sẽ giả định rằng quá trình này đã bị treo và đóng nó ngay lập tức.
Lỗi quá hạn (timeout) này đặc biệt phổ biến với các ứng dụng .NET chạy trên phần cứng cũ hoặc các dịch vụ dựa vào tài nguyên mạng chậm trong giai đoạn khởi động.
Bước 1: Tăng thời gian chờ của dịch vụ qua Registry
Nếu dịch vụ của bạn chỉ cần thêm thời gian để "thở", bạn có thể yêu cầu Windows đợi lâu hơn. Việc sửa đổi giới hạn thời gian chờ toàn cục sẽ giúp mọi dịch vụ trên hệ thống có thêm thời gian để khởi tạo.
- Nhấn
Win + R, nhập regedit và nhấn Enter. - Điều hướng đến đường dẫn sau:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
- Tìm **ServicesPipeTimeout** ở khung bên phải.
- Nếu không thấy, hãy nhấp chuột phải vào khoảng trống, chọn **New > DWORD (32-bit) Value** và đặt tên là `ServicesPipeTimeout`.
- Nhấp chuột phải vào mục đó và chọn **Modify**.
- Đặt **Base** thành **Decimal**.
- Nhập thời gian chờ mong muốn tính bằng mili giây. Sử dụng `60000` cho 60 giây hoặc `180000` cho 3 phút.
- Nhấn OK và **khởi động lại máy tính** để áp dụng giới hạn mới.
## Bước 2: Xác minh các phụ thuộc .NET Framework
Các vấn đề về tương thích có thể khiến dịch vụ bị treo trước khi kịp bắt đầu. Nếu việc chỉnh sửa registry không thành công, dịch vụ có thể đang gặp lỗi vì không tìm thấy môi trường thực thi (runtime) chính xác. Lỗi 1053 thường là một mặt nạ chung cho các lỗi khởi tạo .NET tiềm ẩn.
- Xác nhận máy chủ có chính xác phiên bản .NET Framework mà dịch vụ yêu cầu.
- Kiểm tra sự không khớp về phiên bản. Nếu dịch vụ của bạn hướng tới .NET 4.8 nhưng máy chỉ có .NET 3.5, ứng dụng có khả năng sẽ bị quá hạn trong giai đoạn khởi động ngầm.
- Luôn cài đặt phiên bản **Runtime** từ Microsoft cho các máy chủ thực tế thay vì bản Developer Pack.
## Bước 3: Kiểm tra các tệp DLL hoặc tệp cấu hình bị thiếu
Một dịch vụ có thể bị quá hạn vì bị kẹt trong việc tìm kiếm một phụ thuộc bị thiếu. Do các dịch vụ không có giao diện người dùng, chúng không thể hiển thị cảnh báo "File Not Found". Chúng chỉ đơn giản là chạy quẩn quanh cho đến khi Windows đóng chúng lại.
Kiểm tra tệp thực thi theo cách thủ công bằng Command Prompt để phát hiện các lỗi ẩn này:
C:\Path\To\Your\Service\YourService.exe
Mặc dù ứng dụng cuối cùng sẽ thoát với thông báo rằng nó phải được khởi động thông qua Service Controller, nhưng trước đó nó có thể xuất ra một lỗi nghiêm trọng liên quan đến việc thiếu DLL hoặc tệp `app.config` bị hỏng.
## Bước 4: Sửa lỗi tệp hệ thống bằng SFC
Các dịch vụ chuẩn của Windows, chẳng hạn như Print Spooler, thỉnh thoảng kích hoạt lỗi này do các tệp nhị phân hệ thống bị hỏng. Nếu một dịch vụ tích hợp sẵn của Windows gặp lỗi, hãy sử dụng System File Checker để sửa chữa hư hỏng.
- Chạy Command Prompt với quyền **Administrator**.
- Thực thi lệnh sửa lỗi sau:
```
sfc /scannow
- Để quá trình quét đạt 100%, sau đó khởi động lại máy.
Xác minh
Sau khi bạn đã áp dụng biện pháp khắc phục, hãy thử khởi động lại dịch vụ thông qua services.msc. Sau khi nó khởi động, hãy mở Event Viewer (eventvwr.msc) và điều hướng đến Windows Logs > System. Tìm một mục Information xác nhận rằng dịch vụ đã chuyển sang trạng thái đang chạy thành công.
Mẹo tối ưu hóa cho lập trình viên
Dựa vào các bản chỉnh sửa Registry chỉ là giải pháp tạm thời, không phải là cách chữa trị dứt điểm. Nếu bạn quản lý mã nguồn, hãy sử dụng hai chiến lược sau để loại bỏ hoàn toàn lỗi quá hạn:
1. Chuyển bớt công việc khỏi OnStart
Phương thức OnStart nên đóng vai trò như một phát súng bắt đầu, chứ không phải bản thân cuộc đua. Hãy chuyển các logic nặng nề—như di chuyển cơ sở dữ liệu hoặc lập chỉ mục tệp—sang một luồng nền (background thread) để phương thức có thể trả lại quyền điều khiển cho Windows ngay lập tức.
protected override void OnStart(string[] args)
{
// Bắt đầu một tác vụ nền và trả lại quyền điều khiển ngay lập tức
Task.Run(() => DoHeavyInitialization());
}
2. Sử dụng RequestAdditionalTime
Khi bạn không thể tránh khỏi một quá trình khởi động dài, hãy sử dụng phương thức RequestAdditionalTime. Điều này thông báo cho SCM đặt lại bộ đếm ngược 30 giây, ngăn chặn việc đóng dịch vụ sớm.
protected override void OnStart(string[] args)
{
// Yêu cầu Windows kiên nhẫn thêm 60 giây
this.RequestAdditionalTime(60000);
PerformComplexSetup();
}

