我编写了一个Windows服务,定期执行一个SSIS包,将文档从Server A
移动到Server B
。
问题是,为了做到这一点,我需要使用一个无限循环,它在服务启动时启动。
当然,我将此循环放入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.
}
}
我认为这是一个常见问题,因为大多数服务应该无限期运行。
关于如何让这项服务返回已经开始的任何想法?
谢谢!
答案 0 :(得分:4)
您应该使用System.Threading.Timer
而不是无限循环。
答案 1 :(得分:3)
您的服务应该在不同的线程上完成工作。 OnStart
,OnStop
等方法可以从Windows服务控制管理器(SCM)处理命令到服务,SCM希望它们能够及时返回。
使用@SLaks建议的System.Threading.Timer
实现了这一点:计时器事件将在.NET线程池的线程上执行。 OnStart方法只启用Timer,而OnStop方法禁用它(如果需要,OnPause和OnResume也可以这样做。)
答案 2 :(得分: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
}
答案 3 :(得分: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