后台服务的ASP.NET Core文档显示了许多实现示例。
有一个在计时器上启动服务的示例,尽管它是同步的。还有另一个异步示例,用于启动具有范围依赖项的服务。
我需要同时执行这两项操作:每 5 分钟启动一个服务,并且它具有范围内的依赖项。没有这样的例子。
我结合了这两个示例,但我不确定使用Timerasync 的安全方法TimerCallback。
例如
public class MyScheduler : IHostedService
{
private Timer? _timer;
private readonly IServiceScopeFactory _serviceScopeFactory;
public MyScheduler(IServiceScopeFactory serviceScopeFactory) => _serviceScopeFactory = serviceScopeFactory;
public void Dispose() => _timer?.Dispose();
public Task StartAsync(CancellationToken cancellationToken)
{
_timer = new Timer((object? state) => {
using var scope = _serviceScopeFactory.CreateScope();
var myService = scope.ServiceProvider.GetRequiredService<IMyService>();
await myService.Execute(cancellationToken); // <------ problem
}), null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken …Run Code Online (Sandbox Code Playgroud) c# async-await asp.net-core asp.net-core-hosted-services asp.net-core-5.0
我正在编写一个Windows服务,每隔一段时间运行一次可变长度的活动(数据库扫描和更新).我需要经常运行此任务,但要处理的代码并不安全地同时运行多次.
我怎样才能最简单地设置一个计时器来每隔30秒运行一次任务,而不会重复执行?(我假设System.Threading.Timer这个工作是正确的计时器,但可能会弄错).
我不确定这是否可行,所以我在这里:
我有一系列动作来执行多个
async Task MethodA(...)
{
// some code
// a call to specific Async IO bound method
// some code
}
Run Code Online (Sandbox Code Playgroud)
还有MethodB(),MethodC()等,以及所有的具有完全相同的代码,除了呼叫到特定的异步IO绑定的方法.我试图找到一种方法将任务指针传递给方法,以便我们稍后可以在Method()中执行它.
我目前正在做的是:
private async Task Method(Func<Task<Entity>> func)
{
// some code
var a = await task.Run(func);
// some code
}
var task = async () => await CallToIOBoundTask(params);
Method(task);
Run Code Online (Sandbox Code Playgroud)
但是,此代码每次都会提取一个新线程,这对于IO绑定任务不是必需的,应该避免使用.
那么,有没有办法重构代码,以便不使用ThreadPool线程?目标是拥有这样的代码:
private async Task Method(Task<Entity> task)
{
// some code
var a = await task;
// some code
}
Run Code Online (Sandbox Code Playgroud)
同样重要的是要提到不同的IO调用具有不同的方法签名.此外,任务可以开始仅在Method()正文中执行,而不是之前执行.
我想要一个具有以下属性的计时器:
无论启动多少次调用,只有一个回调线程正在运行
关于间隔,忽略了在回调函数中花费的时间.例如,如果间隔为100毫秒并且回调需要4000毫秒才能执行,则回调将在100毫秒,4100毫秒等时调用.
我看不到任何可用的内容,所以写了下面的代码.有一个更好的方法吗?
/**
* Will ensure that only one thread is ever in the callback
*/
public class SingleThreadedTimer : Timer
{
protected static readonly object InstanceLock = new object();
//used to check whether timer has been disposed while in call back
protected bool running = false;
virtual new public void Start()
{
lock (InstanceLock)
{
this.AutoReset = false;
this.Elapsed -= new ElapsedEventHandler(SingleThreadedTimer_Elapsed);
this.Elapsed += new ElapsedEventHandler(SingleThreadedTimer_Elapsed);
this.running = true;
base.Start();
}
}
virtual public void SingleThreadedTimer_Elapsed(object sender, …Run Code Online (Sandbox Code Playgroud) 我有一个要求,后台服务应该在Process每天凌晨 0:00 运行方法
因此,我的一位团队成员编写了以下代码:
public class MyBackgroundService : IHostedService, IDisposable
{
private readonly ILogger _logger;
private Timer _timer;
public MyBackgroundService(ILogger<MyBackgroundService> logger)
{
_logger = logger;
}
public void Dispose()
{
_timer?.Dispose();
}
public Task StartAsync(CancellationToken cancellationToken)
{
TimeSpan interval = TimeSpan.FromHours(24);
TimeSpan firstCall = DateTime.Today.AddDays(1).AddTicks(-1).Subtract(DateTime.Now);
Action action = () =>
{
Task.Delay(firstCall).Wait();
Process();
_timer = new Timer(
ob => Process(),
null,
TimeSpan.Zero,
interval
);
};
Task.Run(action);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask; …Run Code Online (Sandbox Code Playgroud) 所以对于我的一个项目,我需要每 100 毫秒从一个硬件中获取值。获取需要 x 毫秒。所以我正在寻找但找不到的是一种确保 for/while 总是需要 100 毫秒(或更多)的方法。
所以在伪代码中:
for (int i = 0; i < 100; i++) // Take measurements for 10 seconds
{
// Call some async method that sleeps for 100 ms
this.temperatureList.Add(this.HardwareManager.GetSensorValue(ESensor.Temperature)); // Takes 15 ms
this.temperatureList.Add(this.HardwareManager.GetSensorValue(ESensor.Pressure)); // Takes 30 ms
// await async method to finish
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试了一些异步等待的东西,但我似乎无法理解它。谁能帮我找到一种可靠的方法来以 100 毫秒的间隔进行 10 秒的测量?
编辑:我知道因为我在 Windows 上运行 C#,所以计时并不是一个真正有效的选择。但这在我的问题中并不重要。我的问题是,如何确保 for 循环至少需要(!!!)100 毫秒,同时尽可能接近 100 毫秒。
我正在创建一个需要每 x 秒运行一次的后台服务。它必须位于 .net Framework 中,因为客户端不想升级到核心或在计算机上安装除此应用程序之外的任何内容。所以我只能使用 Windows 服务
我的主要问题是我要进入一个 while(true) 循环来检查经过的时间(是的,我知道我可以使用计时器),并且我不确定是否应该添加一个线程。在循环中休眠或只保留 while(true)。我主要关心的是不要让 CPU/内存超载。
var nextIteration = DateTime.Now.Add(TimeSpan.FromSeconds(timer * (-1)));
while (true)
{
if (nextIteration < DateTime.Now)
{
RunService();
nextIteration = DateTime.Now.Add(TimeSpan.FromSeconds(timer));
}
}
Run Code Online (Sandbox Code Playgroud) c# ×7
async-await ×3
timer ×3
.net ×2
asp.net-core-hosted-services ×2
.net-4.5 ×1
.net-4.8 ×1
asp.net-core ×1
asynchronous ×1
overlap ×1
task ×1
wait ×1