Trong một nghĩa nào đó, SCM không thể đảm bảo rằng ngoại lệ bạn phác thảo sẽ không được ném. Nó không kiểm soát thao tác của dịch vụ đối với thành viên riêng tư - ví dụ: nếu mã dịch vụ bổ sung ảnh hưởng đến _foo
.
Sau khi nói điều này, hãy xem xét kịch bản sau đây để xem lý do tại sao câu trả lời cho câu hỏi cụ thể của bạn rõ ràng là không có:
1) Xây dựng dịch vụ của bạn với những thay đổi sau đây để chứng minh:
public partial class MyService : ServiceBase
{
private Object _foo;
private const string _logName = "MyService Log.txt"; // to support added logging
public MyService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
// demonstrative logging
var threadId = Thread.CurrentThread.ManagedThreadId;
using (var log = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + _logName, true))
{
log.WriteLine("{0}: In OnStart(string[]) on thread ID {1}. Sleeping for 10 seconds...", DateTime.Now, threadId);
}
// Sleep before initializing _foo to allow calling OnStop before OnStart completes unless the SCM synchronizes calls to the methods.
Thread.Sleep(10000);
_foo = new Object();
}
protected override void OnStop()
{
// demonstrative logging added
var threadId = Thread.CurrentThread.ManagedThreadId;
using (var log = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + _logName, true))
{
log.WriteLine("{0}: In OnStop() on thread ID {1}.", DateTime.Now, threadId);
}
if (_foo == null)
{
// demonstrative logging added
using (var log = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + _logName, true))
{
log.WriteLine("{0}: _foo == null", DateTime.Now);
}
throw new Exception("Assignment not visible"); // Can this happen?
}
_foo = null;
}
}
2) Mở một lệnh shell.
3) Mở một trình bao lệnh khác.
4) Trong trình bao lệnh đầu tiên, hãy cài đặt dịch vụ (với sc create
) nếu bạn chưa có, và khởi động nó (với net start
). Bạn sẽ thấy:
Dịch vụ MyService đang bắt đầu .....
Các dấu chấm dấu nên được bổ sung từng người một như SCM đợi sau 10 giây ngủ để bắt đầu dịch vụ.
5) Trong trình bao lệnh thứ hai, hãy thử dừng dịch vụ (với net stop
) trước 10 giây trôi qua. Bạn sẽ thấy:
Dịch vụ đang bắt đầu hoặc dừng. Vui lòng thử lại sau.
Vì vậy, bắt đầu dịch vụ rõ ràng là hoạt động chặn phải hoàn tất trước khi dịch vụ có thể dừng lại.
6) Kiểm tra vỏ lệnh đầu tiên sau 10 giây đã trôi qua. Bạn sẽ thấy:
Dịch vụ MyService đã được bắt đầu thành công.
7) Quay lại trình bao lệnh thứ hai và thử dừng dịch vụ lại. Bạn sẽ thấy:
Dịch vụ MyService đang dừng.
Dịch vụ MyService đã được dừng thành công.
8) Xem lại nhật ký kết quả - ví dụ:
10/22/2013 7:28:55 AM: Trong OnStart (string []) trên thread ID 4. Ngủ trong 10 giây ...
10/22/2013 7:29:17 AM: Trong OnStop() trên thread ID 5.
khởi động và dừng dịch vụ một cách nhanh chóng dễ dàng hơn với hai vỏ lệnh tôi nghĩ; nhưng ví dụ này cũng hoạt động tương tự với một trình bao lệnh.
Cuối cùng, bạn có thể tìm thấy Mitchell Taylor (CoolDadTx) 's câu trả lời cho a similar question in MSDN forums thú vị như tôi đã làm:
Mô hình luồng được sử dụng bởi SCM không chính thức ghi nhận AFAIK. Điều được biết là mỗi dịch vụ được gọi theo chủ đề riêng của nó. Tuy nhiên, SCM có thể hoặc không thể sử dụng một nhóm luồng để tái sử dụng một luồng trên các dịch vụ. Khi một dịch vụ được gọi (bắt đầu, dừng, các lệnh tùy chỉnh, vv), nó được dự kiến sẽ thực hiện nhiệm vụ của nó và quay trở lại một cách nhanh chóng. Có một giới hạn mạnh về việc phải mất bao lâu. Bất cứ điều gì nhiều hơn một sự trở lại nhanh chóng đòi hỏi bạn phải đẩy yêu cầu đến một chủ đề thứ cấp để xử lý. Bản thân SCM chạy trên một luồng riêng biệt, do đó nếu một dịch vụ mất quá nhiều thời gian để phản hồi thì SCM sẽ thấy nó bị treo. Này được thảo luận ở đây: http://msdn.microsoft.com/en-us/library/ms684264(VS.85).aspx
UPDATE:
Riêng lưu ý bài viết Service State Transitions MSDN mà bài viết mà Mitchell Taylor trích dẫn liên kết. Nó chứa một sơ đồ trạng thái khá rõ ràng là & các tài liệu tác giả được xác định chuyển tiếp trạng thái dịch vụ và căn chỉnh với những gì tôi đã nêu ở trên. Nó cũng giải thích liên quan đến sơ đồ trạng thái như thế nào SCM không truyền các yêu cầu điều khiển dịch vụ vào các thời điểm để đảm bảo chỉ các trạng thái chuyển trạng thái được xác định.
Tôi cũng quan tâm đến những gì đảm bảo. Tôi chưa bao giờ thấy một cái gì đó giống như ví dụ của bạn gây ra một vấn đề; tuy nhiên, tôi biết rằng có được các nguồn lực gắn liền với nhận dạng luồng (trong trường hợp của chúng tôi là một mutex) đã gây ra vấn đề cho nhóm của tôi trong quá khứ. –
Tôi đã hỏi cùng một câu hỏi trước đây. Tôi sẽ đào nó ra. – spender
Ở đây bạn (đánh dấu là dupe): [Gọi ServiceBase.OnStart và OnStop ... cùng một trường hợp?] (Http: // stackoverflow.com/questions/10799937/call-servicebase-onstart-and-onstop-same-instance) – spender