2011-02-01 51 views
46

Ive đã tạo một cửa sổ Dịch vụ được gọi là ProxyMonitor và hiện tại đang ở giai đoạn dịch vụ được cài đặt và gỡ cài đặt theo cách tôi muốn.Dịch vụ Windows chạy liên tục

Vì vậy, tôi thực hiện việc áp dụng như sau:

C:\\Windows\\Vendor\\ProxyMonitor.exe /install 

Khá tự giải thích, và sau đó tôi đã đến services.msc và và bắt đầu dịch vụ, nhưng khi tôi làm điều này tôi nhận được thông báo sau:

Dịch vụ giám sát proxy trên máy tính cục bộ bắt đầu và sau đó dừng lại. Một số dịch vụ tự động dừng nếu không có công việc để làm, Ví dụ, các bản ghi hiệu suất và Cảnh báo dịch vụ

Mã của tôi trông giống như vậy:

public static Main(string[] Args) 
{ 
    if (System.Environment.UserInteractive) 
    { 
     /* 
      * Here I have my install logic 
     */ 
    } 
    else 
    { 
     ServiceBase.Run(new ProxyMonitor()); 
    } 
} 

Và sau đó trong lớp ProxyMonitor tôi có:

public ProxyMonitor() 
{ 
} 

protected override void OnStart(string[] args) 
{ 
    base.OnStart(args); 
    ProxyEventLog.WriteEntry("ProxyMonitor Started"); 

    running = true; 
    while (running) 
    { 
     //Execution Loop 
    } 
} 

onStop() Tôi chỉ thay đổi biến số running thành false;

tôi sẽ cần phải làm gì để thực hiện dịch vụ liên tục hoạt động, như tôi sẽ cần phải được giám sát mạng Tôi cần phải theo dõi những thay đổi, vv


Cập nhật: 1

protected override void OnStart(string[] args) 
{ 
    base.OnStart(args); 
    ProxyEventLog.WriteEntry("ProxyMonitor Started"); 

    Thread = new Thread(ThreadWorker); 
    Thread.Start(); 
} 

Trong số ThreadWorker tôi có ProxyEventLogger.WriteEntry("Main thread entered") mà không bị sa thải.

+0

'Chủ đề = Chủ đề mới (ThreadWorker) 'wont work –

+0

Làm việc hoàn toàn tốt đẹp, Tại sao bạn nghĩ rằng nó sẽ thất bại? – RobertPitt

Trả lời

117

Gọi lại OnStart() cần trả lại một cách kịp thời, vì vậy bạn sẽ muốn bắt đầu một chuỗi nơi tất cả công việc của bạn sẽ được thực hiện. Tôi muốn giới thiệu thêm các lĩnh vực sau đây để lớp học của bạn:

using System.Threading; 
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false); 
private Thread _thread; 

Trường _thread sẽ tổ chức một tham chiếu đến đối tượng System.Threading.Thread bạn tạo trong OnStart() gọi lại. Trường _shutdownEvent có cấu trúc sự kiện cấp hệ thống sẽ được sử dụng để báo hiệu luồng ngừng chạy khi tắt dịch vụ.

Trong cuộc gọi lại OnStart(), hãy tạo và bắt đầu chuỗi của bạn.

protected override void OnStart(string[] args) 
{ 
    _thread = new Thread(WorkerThreadFunc); 
    _thread.Name = "My Worker Thread"; 
    _thread.IsBackground = true; 
    _thread.Start(); 
} 

Bạn cần có chức năng có tên WorkerThreadFunc để làm việc này. Nó phải khớp với chữ ký của đại biểu System.Threading.ThreadStart.

private void WorkerThreadFunc() 
{ 
} 

Nếu bạn không đặt bất cứ điều gì trong hàm này, thread sẽ khởi động và sau đó ngay lập tức tắt máy, vì vậy bạn phải đặt một số logic trong đó mà về cơ bản giữ thread còn sống trong khi bạn làm việc của bạn. Đây là nơi mà các _shutdownEvent có ích.

private void WorkerThreadFunc() 
{ 
    while (!_shutdownEvent.WaitOne(0)) { 
     // Replace the Sleep() call with the work you need to do 
     Thread.Sleep(1000); 
    } 
} 

Vòng lặp while kiểm tra ManualResetEvent để xem nó có được "đặt" hay không. Vì chúng tôi đã khởi tạo đối tượng có số false ở trên, séc này trả về false. Bên trong vòng lặp, chúng tôi ngủ trong 1 giây. Bạn sẽ muốn thay thế điều này bằng công việc bạn cần làm - theo dõi cài đặt proxy, v.v.

Cuối cùng, trong gọi lại OnStop() của Dịch vụ Windows, bạn muốn báo hiệu chuỗi ngừng chạy. Điều này rất dễ dàng bằng cách sử dụng _shutdownEvent.

protected override void OnStop() 
{ 
    _shutdownEvent.Set(); 
    if (!_thread.Join(3000)) { // give the thread 3 seconds to stop 
     _thread.Abort(); 
    } 
} 

Hy vọng điều này sẽ hữu ích.

+0

Cảm ơn vì điều đó, tôi đã hiểu tất cả và bây giờ hoạt động như mong đợi :) – RobertPitt

+4

Rất vui được giúp đỡ. Đối với những gì nó có giá trị, tôi đã có một vài hướng dẫn chi tiết SO cho thấy (1) làm thế nào để có đăng nhập của riêng bạn trong Event Viewer (http://stackoverflow.com/questions/593454/easiest-language-for-creating -a-windows-service/593803 # 593803) và (2) cách cài đặt/gỡ cài đặt dịch vụ của bạn mà không yêu cầu InstallUtil.exe (http://stackoverflow.com/questions/1195478/how-to-make-a-net- windows-service-start-right-after-the-installation/1195621 # 1195621). –

+0

Yea cảm ơn rất nhiều sự giúp đỡ của bạn, trước đây tôi đã đọc bài viết đầu tiên của bạn trong tìm kiếm của tôi để chiến thắng, nếu bạn muốn xem mã của tôi, tôi đã đăng nó ở đây và để lại nhận xét về giai đoạn nào. http://pastebin.com/t8QQzXC9 – RobertPitt

0

Tại sao bạn không tạo dự án mới trong giải pháp dịch vụ Windows kiểu của mình? Điều này thiết lập tất cả các cấu trúc bạn cần thực hiện, bao gồm cả các trình xử lý cho các sự kiện bắt đầu/dừng dịch vụ.

+1

Đây là một phần kinh nghiệm đào tạo và tôi muốn tìm hiểu cách thực hiện của nó từ phía dưới. – RobertPitt

+0

Tôi cho rằng ngay cả đối với đào tạo (đặc biệt là đào tạo?) Bạn sẽ làm tốt nhất để tìm hiểu cách VS tạo giàn giáo cho Dịch vụ Windows và sau đó bạn có thể tìm hiểu lý do tại sao nó hoạt động và cách hoạt động. Thay vì từ dưới lên, như bạn đang tìm ra, thì điều này càng bực bội hơn nhiều. –

+0

Điều này đúng, thực tế là điểm đáng tranh cãi, nhưng đó không phải là trường hợp ở đây. Ứng dụng này đạt được 60% và có thể trong ứng dụng tiếp theo của tôi, tôi sẽ bắt đầu ở mẫu Dịch vụ Windows. – RobertPitt

6

Bạn cần thoát trình xử lý OnStart để bộ điều khiển dịch vụ nhận ra rằng dịch vụ của bạn đã thực sự bắt đầu. Để làm cho nó hoạt động như bạn muốn, bạn có thể bắt đầu một bộ đếm thời gian mà ticks tại một khoảng thời gian và các quá trình khi nó ticks.

Edit:

Hãy thử đặt một System.Diagnostics.Debugger.Launch() trong OnStart của bạn để xem những gì đang xảy ra (và đặt một breakpoint trong ThreadWorker). Tôi sẽ khuyên bạn nên gói này trong #if DEBUG để chắc chắn rằng nó không được triển khai.

Tôi chỉ cũng nhận ra rằng bạn không cung cấp cho Thread bạn một cái tên:

Thread myThread = new Thread(ThreadWorker); 
myThread.Start(); 
+0

Nếu có bất kỳ mã trả lại nào, chẳng hạn như 'return 0' hoặc' return false' và chuỗi cũng sẽ ổn? – RobertPitt

+0

Không; trình xử lý sự kiện 'OnStart' trả về void. Miễn là nó thoát trong một khoảng thời gian hợp lý (khoảng một phút, tôi nghĩ), bộ điều khiển dịch vụ sẽ được hạnh phúc. –

+0

Hãy cho nó đi. – RobertPitt

2

Chắc chắn không phải thêm một vòng lặp while trong phương pháp OnStart. Điều này sẽ nói với hệ điều hành rằng dịch vụ chưa bắt đầu vì nó không thể thoát an toàn khỏi phương thức OnStart. Tôi thường tạo một Timer được bật theo phương pháp OnStart. Sau đó, trong phương pháp Ticks, tôi gọi phương thức cần thiết để có được applicatin để chạy.

Ngoài ra, bạn có thể làm như sau:

// The main entry point for the process 
static void Main() 
{ 
    System.ServiceProcess.ServiceBase[] ServicesToRun; 
    ServicesToRun = new System.ServiceProcess.ServiceBase[] { new WinService1() }; 
    System.ServiceProcess.ServiceBase.Run(ServicesToRun); 
} 

Để biết thêm thông tin về dịch vụ Windows, bạn có thể nhận được một ví dụ xương here.

1

Mã mẫu được minh họa bằng ứng dụng bảng điều khiển. hy vọng điều này sẽ giúp ..

class Program 
{ 
    private static CancellationTokenSource _cancellationTokenSource; 
    private static ManualResetEvent _shutdownEvent = new ManualResetEvent(false); 
    private static Thread _serviceStartThread; 
    private static Thread _serviceStopThread; 

    private static int workcounter = 0; 
    static void Main(string[] args) 
    { 

     _cancellationTokenSource = new CancellationTokenSource(); 
     _serviceStartThread = new Thread(DoWork); 
     _serviceStopThread = new Thread(ScheduledStop); 
     StartService(); 
     StopService(); 
    } 

    private static void StartService() 
    { 
     _serviceStartThread.Start(); 

    } 

    private static void StopService() 
    { 
     _serviceStopThread.Start(); 
    } 


    /// <summary> 
    /// Triggers a cancellation event for stopping the service in a timely fashion. 
    /// </summary> 
    private static void ScheduledStop() 
    { 
     while (!_shutdownEvent.WaitOne(0)) 
     { 
      if (workcounter == 10) 
      { 
       _cancellationTokenSource.Cancel(); 
      } 
     } 
    } 

    /// <summary> 
    /// Represents a long running Task with cancellation option 
    /// </summary> 
    private static void DoWork() 
    { 

     while (!_shutdownEvent.WaitOne(0)) 
     { 
      if(!_cancellationTokenSource.Token.IsCancellationRequested) 
      { 
       workcounter += 1; 
       Console.Write(Environment.NewLine); 
       Console.Write("Running...counter: " + workcounter.ToString()); 
       Thread.Sleep(1000);//Not needed, just for demo.. 
      } 
      else 
      { 
       Console.Write(Environment.NewLine); 
       Console.Write("Recieved cancellation token,shutting down in 5 seconds.. counter: " + workcounter.ToString()); 
       _shutdownEvent.Set(); 
       Thread.Sleep(5000);//Not needed, just for demo.. 
      } 

     } 
    } 
} 
Các vấn đề liên quan