- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 WPF 应用程序中,我配置了一个托管服务以在后台执行特定事件(遵循 this article)。这就是在 App.xaml.cs 中配置托管服务的方式。
public App()
{
var environmentName = Environment.GetEnvironmentVariable("HEALTHBOOSTER_ENVIRONMENT") ?? "Development";
IConfigurationRoot configuration = SetupConfiguration(environmentName);
ConfigureLogger(configuration);
_host = Host.CreateDefaultBuilder()
.UseSerilog()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>()
.AddOptions()
.AddSingleton<IMailSender, MailSender>()
.AddSingleton<ITimeTracker, TimeTracker>()
.AddSingleton<NotificationViewModel, NotificationViewModel>()
.AddTransient<NotificationWindow, NotificationWindow>()
.Configure<AppSettings>(configuration.GetSection("AppSettings"));
}).Build();
AssemblyLoadContext.Default.Unloading += Default_Unloading;
Console.CancelKeyPress += Console_CancelKeyPress;
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
}
并在启动时开始
/// <summary>
/// Handles statup event
/// </summary>
/// <param name="e"></param>
protected override async void OnStartup(StartupEventArgs e)
{
try
{
Log.Debug("Starting the application");
await _host.StartAsync(_cancellationTokenSource.Token);
base.OnStartup(e);
}
catch (Exception ex)
{
Log.Error(ex, "Failed to start application");
await StopAsync();
}
}
现在我想在系统进入休眠状态时停止托管服务,并在系统恢复时重新启动服务。我试过了
/// <summary>
/// Handles system suspend and resume events
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
switch (e.Mode)
{
case PowerModes.Resume:
Log.Warning("System is resuming. Restarting the host");
try
{
_cancellationTokenSource = new CancellationTokenSource();
await _host.StartAsync(_cancellationTokenSource.Token);
}
catch (Exception ex)
{
Log.Error(ex, $"{ex.Message}");
}
break;
case PowerModes.Suspend:
Log.Warning("System is suspending. Canceling the activity");
_cancellationTokenSource.Cancel();
await _host.StopAsync(_cancellationTokenSource.Token);
break;
}
}
停止主机工作正常但是当主机重新启动时,我收到“System.OperationCanceledException
”。根据我的理解,托管服务生命周期独立于应用程序生命周期。我的理解错了吗?
这个问题- ASP.NET Core IHostedService manual start/stop/pause(?)是相似的,但答案是暂停并重新启动基于配置的服务,这看起来像是 hack,所以我正在寻找一种标准方法。
有什么想法吗?
最佳答案
作为Stephen Cleary在评论中指出,worker 可以独立于主机启动和停止,但理想情况下主机应该处理 worker 的生命周期。
但是由于 .NET Core 3 中存在一个错误,传递给 IHostedService
StartAsync
方法的取消标记不会传播给工作人员 ExecuteAsync
方法。我为此创建了一个问题,可以在此处找到详细信息 - https://github.com/dotnet/extensions/issues/3218
错误修复 (https://github.com/dotnet/extensions/pull/2823) 将成为 .NET 5 的一部分,因此按照问题 (https://github.com/dotnet/extensions/issues/3218#issuecomment-622503957) 中的建议,我必须创建自己的类来模仿框架的 BackGroundService
类并且此类将直接继承自 IHostedService
并将取消 token 传播给工作人员。
BackGroundService
类自定义实现在这里 -
/// <summary>
/// Base class for implementing a long running <see cref="IHostedService"/>.
/// </summary>
public abstract class BGService : IHostedService, IDisposable
{
private Task _executingTask;
private CancellationTokenSource _stoppingCts;
/// <summary>
/// This method is called when the <see cref="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="IHostedService.StopAsync(CancellationToken)"/> is called.</param>
/// <returns>A <see cref="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)
{
// Create linked token to allow cancelling executing task from provided token
_stoppingCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
// Store the task we're executing
_executingTask = ExecuteAsync(_stoppingCts.Token);
// If the task is completed then return it, this will bubble cancellation and failure to the caller
if (_executingTask.IsCompleted)
{
return _executingTask;
}
// Otherwise it's running
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)
{
// Stop called without start
if (_executingTask == null)
{
return;
}
try
{
// Signal cancellation to the executing method
_stoppingCts.Cancel();
}
finally
{
// Wait until the task completes or the stop token triggers
await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, cancellationToken));
}
}
public virtual void Dispose()
{
_stoppingCts?.Cancel();
}
}
以及分别在系统挂起和恢复时停止和启动worker的逻辑
/// <summary>
/// Handles system suspend and resume events
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
var workers = _host.Services.GetServices<IHostedService>();
Log.Information($"Found IHostedService instances - {workers.ToCSV()}");
switch (e.Mode)
{
case PowerModes.Resume:
Log.Warning("System is resuming. Restarting the workers");
try
{
_cancellationTokenSource = new CancellationTokenSource();
foreach (var worker in workers)
{
await worker.StartAsync(_cancellationTokenSource.Token);
}
}
catch (Exception ex)
{
Log.Error(ex, $"{ex.Message}");
}
break;
case PowerModes.Suspend:
Log.Warning("System is suspending. Stopping the workers");
_cancellationTokenSource.Cancel();
try
{
foreach (var worker in workers)
{
await worker.StopAsync(_cancellationTokenSource.Token);
}
}
catch (Exception ex)
{
Log.Error(ex, $"{ex.Message}");
}
break;
}
}
请注意@davidfowl 建议这不是受支持的功能 (https://github.com/dotnet/extensions/issues/3218#issuecomment-623280990),但我在使用这种方法时没有遇到任何问题,并且相信这也应该是受支持的用例。
关于c# - 如何停止和恢复 worker 服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61496138/
我正在使用 Tkinter 在 python 上写一个小游戏(顺便说一下,我不允许使用任何其他非内置模块)并且我想在主窗口上播放背景歌曲,这是那个包含标题,以及转到其他窗口和内容的按钮... 所以问题
我有一个 Azure WebJob,它在一个非常简单的应用服务标准:1 Small(计划)上运行。 现在,我的 WebJob(有 5 个函数正在运行)出现问题 - 我想停止 5 个正在运行的函数中的
我在 MacOS Lion 上使用 XCode 4.2。在模拟器中调试 iPhone/iPad 应用程序时,我使用 XCode 工具栏上的“停止”按钮(产品 | 停止)退出应用程序。在此之后,XCod
我刚刚下载了android开放源代码项目,并尝试使用make来构建它,我收到了以下消息: build/core/prebuilt.mk:91: *** recipe commences before
我以前从未制作过 makefile,但我们已经收到了这个,但是,如果我尝试运行它,它只会说, missing separator. stop. 我不知道可能出了什么问题 - 我已经确保空格只按制表符。
好吧,这段代码非常基本。用户将答案输入文本框,如果等于“第一+第二”,他们就得到一分。然后,他们有 5 秒钟的时间回答下一个数学问题。如果他们这样做了,函数“doCalculation”将再次运行,他
我在 viewController 中有一个循环动画 - (void)moveAnimating { [UIView animateWithDuration:2.0f animations:^
当我有一个待处理的 ASIFormDataRequest(作为异步任务启动)仍在执行并且用户按下后退按钮(为了弹出 View )时,我的 viewController 出现问题。 有什么方法可以停止该
我们正在使用 flashdevelop 和 flash CS 3 开发基于 flash 的游戏。我们正在使用 flash CS3 发布 swc,swc 将作为库在 flashdevlop 中使用。 一
我在线程中有一个连接,因此我将其添加到运行循环中以获取所有数据: [[NSRunLoop currentRunLoop] run]; [connection scheduleInRunLoop
你好,我做了一个 php 套接字服务器来从 plc 获取数据,plc 被配置为 tcp 套接字客户端。 我有一个严重的问题,如果本地网络出现故障,似乎功能 socket_accept 停止,plc 无
这个问题已经有答案了: How to stop a setTimeout loop? (10 个回答) 已关闭 8 年前。 请帮助获得正确的函数或方法来停止 setTimeout 函数。 我一直在尝试
我正在运行一个多项目SBT(v0.13)构建,并且希望它在子项目中遇到的第一个错误(编译)时快速失败(停止)。 当前的行为是,当某项无法在子项目中进行编译时,构建将继续(以编译所有其他子项目)。 一旦
我有播放.wav文件中声音的代码,但是我无法停止播放歌曲,甚至无法退出程序直到播放结束。因为这是一首5分钟的歌曲,所以这是一个问题。这是我如何播放wav的代码: public class EasySo
我正在寻找一种解决方案,该如何控制从JSF应用程序播放音频文件。 我不需要完整的解决方案,只需引用我可以用来控制播放音频文件(开始/停止/更改声音)的组件即可。 我尝试搜索过去的问题,但没有成功。 我
我已经在test.ps1中编写了以下函数,在运行该脚本以启动/停止/ ..时我想做一个选择: function getState($SeviceName) { $server = @('hos
我必须设置一个 10 分钟的计时器,它会重定向到主屏幕。此外,它必须在每个操作(例如按下按钮)时重置。我找到了这个计时器:https://github.com/fengyuanchen/vue-cou
我正在制作一个聊天应用程序,功能之一就是发送声音。发送的HTML如下: LOL Stop Play 第一次发送时,“自动播放”效果很好。因此,现在我
我基本上希望页面能够接受用户输入的时间(以秒为单位)。 之后我希望当用户按下“开始”按钮时开始倒计时按下暂停按钮时“暂停”。还有一个重置按钮,以便用户可以从头开始倒计时。 这是我到目前为止得到的:
我需要停止 $.each 循环,加载图像,然后继续循环。我有 Canvas ,可以在其中加载对象图像。对象以正确的顺序排列在数组中。现在,当我尝试从数组加载对象时,存在一个问题:由于尺寸不同,并且它们
我是一名优秀的程序员,十分优秀!