Câu trả lời:
Cập nhật:
Gần bốn năm sau câu trả lời ban đầu của tôi và câu trả lời này đã rất lỗi thời. Kể từ khi TopShelf xuất hiện cùng với việc phát triển Dịch vụ Windows trở nên dễ dàng. Bây giờ bạn chỉ cần tìm ra cách hỗ trợ chuyển đổi dự phòng ...
Câu trả lời gốc:
Tôi thực sự không phải là một fan hâm mộ của Windows Scheduler. Mật khẩu của người dùng phải được cung cấp như @moodforall đã chỉ ra ở trên, điều này thật thú vị khi ai đó thay đổi mật khẩu của người dùng đó.
Khó chịu lớn khác với Windows Scheduler là nó chạy tương tác chứ không phải là một quá trình nền. Khi 15 cửa sổ MS-DOS bật lên sau mỗi 20 phút trong một phiên RDP, bạn sẽ bắt đầu tự cài đặt chúng dưới dạng Windows Services.
Dù bạn chọn, tôi chắc chắn khuyên bạn nên tách mã xử lý của mình thành một thành phần khác với ứng dụng bảng điều khiển hoặc Dịch vụ Windows. Sau đó, bạn có sự lựa chọn, gọi tiến trình công nhân từ một ứng dụng bảng điều khiển và kết nối nó vào Trình lập lịch Windows hoặc sử dụng Dịch vụ Windows.
Bạn sẽ thấy rằng việc lên lịch cho Dịch vụ Windows không thú vị. Một tình huống khá phổ biến là bạn có một tiến trình đang chạy dài mà bạn muốn chạy định kỳ. Nhưng, nếu bạn đang xử lý một hàng đợi, thì bạn thực sự không muốn hai trường hợp của cùng một công nhân xử lý cùng một hàng đợi. Vì vậy, bạn cần quản lý bộ đếm thời gian, để đảm bảo nếu quá trình chạy dài của bạn đã chạy lâu hơn khoảng thời gian được chỉ định, nó sẽ không khởi động lại cho đến khi quá trình hiện có kết thúc.
Sau khi bạn đã viết tất cả những điều đó, bạn nghĩ, tại sao tôi không sử dụng Thread.Sleep? Điều đó cho phép tôi để luồng hiện tại tiếp tục chạy cho đến khi nó kết thúc và sau đó khoảng thời gian tạm dừng bắt đầu, luồng chuyển sang trạng thái ngủ và bắt đầu lại sau thời gian cần thiết. Khéo léo!
Sau đó, bạn đọc tất cả các lời khuyên trên internet với rất nhiều chuyên gia cho bạn biết thực hành lập trình thực sự tồi tệ như thế nào:
Vì vậy, bạn sẽ vò đầu bứt tai và tự nghĩ, WTF, Hoàn tác thanh toán đang chờ xử lý -> Vâng, tôi chắc chắn -> Hoàn tác tất cả công việc hôm nay ..... chết tiệt, chết tiệt, chết tiệt ...
Tuy nhiên, tôi thích mô hình này, ngay cả khi mọi người nghĩ rằng nó là tào lao:
Phương thức OnStart cho phương pháp đơn luồng.
protected override void OnStart (string args) { // Create worker thread; this will invoke the WorkerFunction // when we start it. // Since we use a separate worker thread, the main service // thread will return quickly, telling Windows that service has started ThreadStart st = new ThreadStart(WorkerFunction); workerThread = new Thread(st); // set flag to indicate worker thread is active serviceStarted = true; // start the thread workerThread.Start(); }
Mã khởi tạo một luồng riêng biệt và gắn hàm worker của chúng tôi vào đó. Sau đó, nó bắt đầu chuỗi và cho phép sự kiện OnStart hoàn tất, để Windows không nghĩ rằng dịch vụ bị treo.
Phương pháp công nhân cho phương pháp đơn luồng.
/// <summary> /// This function will do all the work /// Once it is done with its tasks, it will be suspended for some time; /// it will continue to repeat this until the service is stopped /// </summary> private void WorkerFunction() { // start an endless loop; loop will abort only when "serviceStarted" // flag = false while (serviceStarted) { // do something // exception handling omitted here for simplicity EventLog.WriteEntry("Service working", System.Diagnostics.EventLogEntryType.Information); // yield if (serviceStarted) { Thread.Sleep(new TimeSpan(0, interval, 0)); } } // time to end the thread Thread.CurrentThread.Abort(); }
Phương pháp OnStop cho phương pháp đơn luồng.
protected override void OnStop() { // flag to tell the worker process to stop serviceStarted = false; // give it a little time to finish any pending work workerThread.Join(new TimeSpan(0,2,0)); }
Nguồn: http://tutorials.csharp-online.net/Creating_a_.NET_Windows_Service%E2%80%94Alternative_1%3a_Use_a_Separate_Thread (Dead Link)
Tôi đã chạy nhiều Dịch vụ Windows như thế này trong nhiều năm và nó phù hợp với tôi. Tôi vẫn chưa thấy một mô hình được đề xuất mà mọi người đồng ý. Chỉ cần làm những gì phù hợp với bạn.
NT AUTHORITY\NetworkService
là tài khoản có đặc quyền hạn chế.
Một số thông tin sai lệch ở đây. Windows Scheduler hoàn toàn có khả năng chạy các tác vụ trong nền mà không cần cửa sổ bật lên và không cần mật khẩu. Chạy nó trong tài khoản NT AUTHORITY \ SYSTEM. Sử dụng công tắc schtasks này:
/ ru HỆ THỐNG
Nhưng có, để truy cập tài nguyên mạng, cách tốt nhất là tài khoản dịch vụ có chính sách mật khẩu không hết hạn riêng biệt.
BIÊN TẬP
Tùy thuộc vào hệ điều hành của bạn và yêu cầu của chính tác vụ, bạn có thể sử dụng các tài khoản ít đặc quyền hơn Hệ thống địa phương với /ru
tùy chọn.
Từ hướng dẫn sử dụng tốt ,
/RU username
A value that specifies the user context under which the task runs.
For the system account, valid values are "", "NT AUTHORITY\SYSTEM", or "SYSTEM".
For Task Scheduler 2.0 tasks, "NT AUTHORITY\LOCALSERVICE", and
"NT AUTHORITY\NETWORKSERVICE" are also valid values.
Task Scheduler 2.0 có sẵn trên Vista và Server 2008.
Trong XP và Server 2003, system
là lựa chọn duy nhất.
Local Service
(aka NT AUTHORITY\LocalService
) chứ không phải LocalSystem
(aka .\LocalSystem
). Các cựu có quyền hạn chế, trong khi sau này là một quản trị viên
LocalService
và NetworkService
có sẵn trong schtasks
v2 Vista trở đi và nên được ưu tiên nếu có thể. Vào thời điểm đó, điều này đề cập đến schtasks
trong XP và Server 2003 chỉ chấp nhận System
tham số theo hướng dẫn sử dụng phiên bản cũ technet.microsoft.com/en-us/library/bb490996.aspx
Chi phí khởi động và thoát ứng dụng là gì? Hai phút một lần là khá thường xuyên. Một dịch vụ có thể sẽ cho phép hệ thống chạy trơn tru hơn so với việc thực thi ứng dụng của bạn thường xuyên.
Cả hai giải pháp đều có thể chạy chương trình khi người dùng chưa đăng nhập, vì vậy không có sự khác biệt ở đó. Tuy nhiên, việc viết một dịch vụ có liên quan nhiều hơn một ứng dụng máy tính để bàn thông thường - bạn có thể cần một ứng dụng khách GUI riêng biệt sẽ giao tiếp với ứng dụng dịch vụ thông qua TCP / IP, các đường ống được đặt tên, v.v.
Từ POV của người dùng, tôi tự hỏi cái nào dễ kiểm soát hơn. Cả dịch vụ và tác vụ đã lên lịch đều nằm ngoài khả năng của hầu hết người dùng không phải là kỹ thuật, tức là họ thậm chí sẽ không nhận ra chúng tồn tại và có thể được định cấu hình / dừng / lên lịch lại, v.v.
Trong quá trình phát triển .NET, tôi thường bắt đầu bằng cách phát triển Ứng dụng bảng điều khiển, ứng dụng này sẽ chạy tất cả các kết quả ghi nhật ký vào cửa sổ bảng điều khiển. Tuy nhiên, đây chỉ là một Ứng dụng Console khi nó được chạy với đối số lệnh /console
. Khi nó được chạy mà không có tham số này, nó hoạt động như một Dịch vụ Windows, sẽ tiếp tục chạy trên bộ hẹn giờ được lập lịch được mã hóa tùy chỉnh của riêng tôi.
Theo tôi, Windows Services thường được sử dụng để quản lý các ứng dụng khác chứ không phải là một ứng dụng chạy lâu dài. HOẶC .. chúng là các ứng dụng nặng liên tục chạy như SQL Server, BizTalk, RPC Connections, IIS (mặc dù về mặt kỹ thuật IIS giảm tải cho các quy trình khác).
Cá nhân tôi ưu tiên các tác vụ đã lên lịch hơn Dịch vụ Window cho các tác vụ và ứng dụng bảo trì thay thế như sao chép / đồng bộ hóa tệp, gửi email hàng loạt, xóa hoặc lưu trữ tệp, sửa dữ liệu (khi không có các giải pháp thay thế khác).
Đối với một dự án, tôi đã tham gia vào việc phát triển 8 hoặc 9 Dịch vụ Windows, nhưng những dịch vụ này nằm trong bộ nhớ, không hoạt động, ăn 20MB bộ nhớ trở lên cho mỗi phiên bản. Các tác vụ đã lên lịch sẽ thực hiện công việc của chúng và giải phóng bộ nhớ ngay lập tức.
Từ 'serv'ice có điểm chung với' serv'er. Nó dự kiến sẽ luôn chạy và 'serv'e. Một nhiệm vụ là một nhiệm vụ.
Đóng vai. Nếu tôi đang sử dụng hệ điều hành, ứng dụng hoặc thiết bị khác và tôi gọi một dịch vụ, tôi hy vọng nó sẽ chạy và tôi mong đợi phản hồi. Nếu tôi (hệ điều hành, ứng dụng, nhà phát triển) chỉ cần thực thi một tác vụ riêng biệt, thì tôi sẽ thực thi một tác vụ, nhưng nếu tôi muốn giao tiếp, có thể là giao tiếp hai chiều, tôi muốn có một dịch vụ. Điều này liên quan đến cách hiệu quả nhất để hai thứ có thể giao tiếp hoặc một thứ muốn thực hiện một nhiệm vụ duy nhất.
Sau đó, có khía cạnh lập lịch trình. Nếu bạn muốn thứ gì đó chạy vào một thời điểm cụ thể, hãy lên lịch. Nếu bạn không biết khi nào bạn sẽ cần nó, hoặc cần nó "ngay lập tức", hãy dịch vụ.
Câu trả lời của tôi mang tính triết học hơn vì điều này rất giống với cách con người tương tác và làm việc với người khác. Chúng ta càng hiểu rõ nghệ thuật giao tiếp và các "thực thể" hiểu vai trò của họ, thì quyết định này càng trở nên dễ dàng hơn.
Tất cả triết lý sang một bên, khi bạn đang "tạo mẫu nhanh chóng", như Phòng CNTT của tôi thường làm, bạn sẽ làm bất cứ điều gì bạn phải làm để kiếm sống qua ngày. Một khi quá trình tạo mẫu và bằng chứng về nội dung khái niệm không được thực hiện, thường là trong quá trình lập kế hoạch và khám phá ban đầu, bạn phải quyết định điều gì đáng tin cậy hơn cho sự bền vững lâu dài.
OK, vì vậy kết luận, nó phụ thuộc nhiều vào nhiều yếu tố, nhưng hy vọng điều này đã cung cấp cái nhìn sâu sắc thay vì nhầm lẫn.
Một dịch vụ Windows không cần phải có bất kỳ ai đăng nhập và Windows có các phương tiện để dừng, khởi động và ghi lại kết quả dịch vụ.
Một tác vụ đã lên lịch không yêu cầu bạn học cách viết một dịch vụ Windows.
NT AUTHORITY\LocalService
hoặc NT AUTHORITY\NetworkService
). Mọi mật khẩu được cung cấp đều bị bỏ qua vì tài khoản không có mật khẩu.
Tại sao không cung cấp cả hai?
Trước đây, tôi đã đặt các bit 'cốt lõi' trong một thư viện và gói một lệnh gọi tới Anything.GoGoGo () trong cả một dịch vụ cũng như một ứng dụng console.
Với một cái gì đó bạn bắn ra sau mỗi hai phút, tỷ lệ cược là tốt, nó không hoạt động nhiều (ví dụ chỉ là một chức năng loại "ping"). Các trình bao bọc không nhất thiết phải chứa nhiều hơn một lệnh gọi phương thức đơn lẻ và một số bản ghi.
Đây là một câu hỏi cũ nhưng tôi sẽ muốn chia sẻ những gì tôi đã phải đối mặt.
Gần đây, tôi được yêu cầu chụp ảnh màn hình radar (từ trang web Khí tượng) và lưu nó vào máy chủ 10 phút một lần.
Điều này yêu cầu tôi sử dụng WebBrowser. Tôi thường tạo các dịch vụ windows nên tôi cũng quyết định làm một dịch vụ này nhưng nó sẽ tiếp tục bị lỗi. Đây là những gì tôi thấy trong Trình xem sự kiện đường dẫn mô-đun : C: \ Windows \ system32 \ MSHTML.dll
Vì nhiệm vụ khẩn cấp và tôi có rất ít thời gian để nghiên cứu và thử nghiệm, tôi quyết định sử dụng một ứng dụng console đơn giản và kích hoạt nó như một nhiệm vụ và nó thực thi trơn tru.
Tôi thực sự thích bài viết của Jon Galloway đề xuất trong câu trả lời được chấp nhận bởi Mark Ransom.
Gần đây, mật khẩu trên các máy chủ đã bị thay đổi mà tôi không xác nhận và tất cả các dịch vụ không thể thực thi vì chúng không thể đăng nhập. Vì vậy, ppl tuyên bố trong bài viết bình luận rằng đây là một vấn đề. Tôi nghĩ rằng các dịch vụ windows có thể gặp phải vấn đề tương tự (Vui lòng sửa cho tôi nếu tôi sai, tôi chỉ là một người mới)
Ngoài ra, điều được đề cập, nếu sử dụng cửa sổ lập lịch tác vụ bật lên hoặc cửa sổ bảng điều khiển bật lên. Tôi chưa bao giờ đối mặt với điều đó. Nó có thể bật lên nhưng ít nhất là rất tức thời.
Nói chung, thông điệp cốt lõi là và phải là bản thân mã phải có thể thực thi được từ mỗi và mọi "trigger / client". Vì vậy, nó không nên là khoa học tên lửa để chuyển từ cách tiếp cận này sang cách tiếp cận khác.
Trước đây, chúng tôi ít nhiều sử dụng Dịch vụ Windows nhưng vì ngày càng nhiều khách hàng của chúng tôi chuyển sang Azure từng bước và việc hoán đổi từ Ứng dụng Console (được triển khai dưới dạng Tác vụ đã lên lịch) sang WebJob trong Azure dễ dàng hơn nhiều so với từ Dịch vụ Windows, hiện tại chúng tôi tập trung vào Công việc đã lên lịch. Nếu chúng tôi gặp phải những hạn chế, chúng tôi chỉ cần tăng cường dự án Windows Service và gọi cùng một logic từ đó (miễn là khách hàng đang làm việc OnPrem ..) :)
BR, y
Các dịch vụ Windows cần thêm sự kiên nhẫn cho đến khi hoàn tất. Nó có một chút khó gỡ lỗi và cài đặt. Nó không có khuôn mặt. Nếu bạn cần một tác vụ phải thực hiện trong mỗi giây, phút hoặc giờ, bạn nên chọn Windows Service.
Nhiệm vụ theo lịch trình được phát triển nhanh chóng và có mặt. Nếu bạn cần một nhiệm vụ hàng ngày hoặc hàng tuần, bạn có thể sử dụng Tác vụ đã lên lịch.