2011-01-05 53 views
2

我已經編寫了一個Windows服務,它定期執行一個SSIS包,將文件從Server A移動到Server B由於OnStart()方法中的無限循環,Windows服務始終「啓動」

的問題是,爲了做到這一點,我需要用一個無限循環,在服務啓動時啓動。

當然,我置於該環路進入OnStart()方法。不幸的是,服務永遠不會發出信號,它已經開始,因爲它從來沒有達到這個方法結束...

下面是相關代碼:

protected override void OnStart(string[] args) 
{ 
    Application app = new Application(); 
    Package pkg = app.LoadFromDtsServer(@"MSDB\PullDoc", "Server", null); 
    while (true) 
    { 
     DTSExecResult pkgResults = pkg.Execute();//Execute the package. 
     EventLog.WriteEntry(pkgResults.ToString()); 
     Thread.Sleep(1000 * 60 * 5);//Sleep at least five minutes. 
    } 
} 

我會想象這是一個普遍的問題,給出大多數服務應該無限期地運行。

有關如何讓此服務返回已啓動的任何想法?

謝謝!

回答

4

您應該使用System.Threading.Timer而不是無限循環。

+0

相關問題:當​​我使用計時器時,即使方法尚未執行完畢,它也會每5分鐘調用我的回調方法。有沒有一種簡單的方法,使其不計數直到方法結束? – nosirrahcd 2011-01-05 20:23:02

+0

@user:將計時器設置爲只運行一次,然後在方法結束時重新啓動計時器。 – SLaks 2011-01-05 20:24:40

3

你的服務應該在不同的線程上工作。 OnStartOnStop等方法可用於從Windows服務控制管理器(SCM)處理到您的服務的命令,SCM期望它們立即返回。

使用由@SLaks提出了System.Threading.Timer實現這一點:計時器事件會從.NET線程池中的線程來執行。您的OnStart方法只是啓用計時器,而OnStop方法則禁用它(如果需要,OnPause和OnResume也可以這樣做)。

2

你沒有正確地做到這一點,你不應該阻止函數返回,你應該使用一個新的線程。如所建議的那樣,您應該使用Timer對象。 下面的代碼片段向您展示如何:

private void OnElapsedTime(object source, ElapsedEventArgs e) 
    { 
     CopyAToB(); 
    } 
    Timer timer = new Timer(); 
    protected override void OnStart(string[] args) 
    { 
     timer.Elapsed += new ElapsedEventHandler(OnElapsedTime); 
     timer.Interval = 60000 * 5; 
     timer.Enabled = true; 
    } 
    private void CopyAToB() 
    { 
     // do somethings 
    } 
+0

在Windows服務中,您需要使用System.Timers.Timer或System.Threading.Timer。看到這個職位的更詳細的解釋http://stackoverflow.com/questions/246697/windows-service-and-timer – Zman101 2011-01-06 15:26:21

1

我會建議你使用像提出了System.Threading.Timer,但這裏是我將如何實現該功能的例子。

在這個例子中,我具有的功能火一小時的4倍,它會迅速地驗證如果仍從以前的調用運行,如果是這樣跳過它,否則將創建一個新的線程和火關閉該功能。

Imports System.Threading 

Public Class myService 

    Private myThreadingTimer As System.Threading.Timer 
    Private keepRunning As Boolean = False 
    Private processing As Boolean = False 

    Protected Overrides Sub OnStart(ByVal args() As String) 
    Dim myTimerCallback As New TimerCallback(AddressOf OnTimedEvent) 

    If YourCheckHere() Then 
     keepRunning = True 
     myThreadingTimer = New System.Threading.Timer(myTimerCallback, Nothing, 1000, 1000) 
    Else 
     'What you want to do here 
    End If 
    End Sub 

    Protected Overrides Sub OnStop() 
    keepRunning = False 
    End Sub 

    Private Sub OnTimedEvent(ByVal state As Object) 
    If Date.Now.Minute = 14 And Date.Now.Second = 31 Or Date.Now.Minute = 29 And Date.Now.Second = 31 _ 
    Or Date.Now.Minute = 44 And Date.Now.Second = 31 Or Date.Now.Minute = 59 And Date.Now.Second = 31 _ 
    Then 
     'Make Sure Its Supposed To Still Be Running 
     If keepRunning Then 
     'Make Sure The Process Is Not Already Running 
     If Not processing Then 
      'Process is not currently running lets start it 
      Dim myThread As New Thread(New ThreadStart(AddressOf myProcess)) 
      myThread.Start() 
     End If 
     End If 
    End If 
    End Sub 

    Public Sub myProcess() 
    Try 
     ' Set the processing flag so the function does not run again until complete 
     processing = True 

     'Do whatever logic you need here 

    Catch ex As Exception 
     'Since You Can Not Use A MessageBox Do Logging Or Whatever You Need Here 

    Finally 
     processing = False 
    End Try 
    End Sub 

End Class