【发布时间】:2019-03-09 15:18:02
【问题描述】:
我有一个简单的 .net 核心控制台应用程序,其中包含几个长时间运行的后台服务。服务在应用程序启动时启动。我想根据用户请求正确停止它们。微软提供了实现长期运行的基类——BackgroundService。
public abstract class BackgroundService : IHostedService, IDisposable
{
private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource();
private Task _executingTask;
/// <summary>
/// This method is called when the <see cref="T:Microsoft.Extensions.Hosting.IHostedService" /> starts. The implementation should return a task that represents
/// the lifetime of the long running operation(s) being performed.
/// </summary>
/// <param name="stoppingToken">Triggered when <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StopAsync(System.Threading.CancellationToken)" /> is called.</param>
/// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the long running operations.</returns>
protected abstract Task ExecuteAsync(CancellationToken stoppingToken);
/// <summary>
/// Triggered when the application host is ready to start the service.
/// </summary>
/// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
public virtual Task StartAsync(CancellationToken cancellationToken)
{
this._executingTask = this.ExecuteAsync(this._stoppingCts.Token);
if (this._executingTask.IsCompleted)
return this._executingTask;
return Task.CompletedTask;
}
/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// </summary>
/// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
public virtual async Task StopAsync(CancellationToken cancellationToken)
{
if (this._executingTask == null)
return;
try
{
this._stoppingCts.Cancel();
}
finally
{
Task task = await Task.WhenAny(this._executingTask, Task.Delay(-1, cancellationToken));
}
}
public virtual void Dispose()
{
this._stoppingCts.Cancel();
}
BackgroundService 允许通过调用方法StopAsync 停止服务。
我们也可以通过这种方式实现长时间运行的服务,使用单一方法和取消令牌:
public class LongRunningService
{
public Task RunAsync(CancellationToken token)
{
return Task.Factory.StartNew(() =>
{
// here goes something long running
while (!token.IsCancellationRequested)
{
}
},
TaskCreationOptions.LongRunning);
}
}
这两种方法都解决了我的问题。但是在代码组织和匹配类语义方法方面,我无法确定哪一个更好。你会选择什么方法,为什么?
【问题讨论】:
标签: .net architecture .net-core task-parallel-library