在Windows服务中执行任务循环的最佳方法

GuF*_*edo 16 c# multithreading windows-services task-parallel-library async-await

我有一种方法可以向我们的客户发送一些短信,如下所示:

public void ProccessSmsQueue()
{
   SmsDbContext context = new SmsDbContext();
   ISmsProvider provider = new ZenviaProvider();
   SmsManager manager = new SmsManager(context, provider);

   try
   {
      manager.ProcessQueue();
   }
   catch (Exception ex)
   {
      EventLog.WriteEntry(ex.Message, EventLogEntryType.Error);
   }
   finally
   {
      context.Dispose();
   }
}

protected override void OnStart(string[] args)
{
   Task.Factory.StartNew(DoWork).ContinueWith( ??? )
}
Run Code Online (Sandbox Code Playgroud)

所以,我有一些问题:

  1. 我不知道方法运行需要多长时间;

  2. 该方法可以抛出异常,我想在EventLog上编写

  3. 我希望每10分钟在循环中运行此方法,但仅在最后一次执行完成后.

我怎么能做到这一点?我考虑过使用ContinueWith(),但我仍然对如何构建整个逻辑有疑问.

i3a*_*non 32

你应该有一个接受a的异步方法,CancellationToken它知道何时停止,ProccessSmsQueuetry-catch块中调用并使用Task.Delay异步等待直到下次需要运行:

public async Task DoWorkAsync(CancellationToken token)
{
    while (true)
    {
        try
        {
            ProccessSmsQueue();
        }
        catch (Exception e)
        {
            // Handle exception
        }
        await Task.Delay(TimeSpan.FromMinutes(10), token);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在应用程序启动时调用此方法,并Task.Wait在返回的任务存在之前调用此方法,以便您知道它完成且没有例外:

private Task _proccessSmsQueueTask;
private CancellationTokenSource _cancellationTokenSource;

protected override void OnStart(string[] args)
{
    _cancellationTokenSource = new CancellationTokenSource();
    _proccessSmsQueueTask = Task.Run(() => DoWorkAsync(_cancellationTokenSource.Token));
}

protected override void OnStop()
{
    _cancellationTokenSource.Cancel();
    try
    {
        _proccessSmsQueueTask.Wait();
    }
    catch (Exception e)
    {
        // handle exeption
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @juzamn`OnStart`返回`void`所以它将是一个`async void`方法,你只能用于事件处理程序. (4认同)