英文:
.Net core 6 - About Async Task run in constructor, the VSCode Debugger is not work
问题
我有一个需要不断轮询设备信息的任务,所以我在构造函数中创建了这个任务。
public DeviceManager()
{
Task.Run(Polling);
}
private Func<Task> Polling()
{
return async () =>
{
while (true)
{
await GetInfo();
await Task.Delay(60 * 1000);
}
}
}
通常我会运行 dotnet watch --no-hot-reload
来测试我的程序,但现在我想要调试它。
然而,当调试器运行时,它卡在这个 while 循环中。
请告诉我为什么我不能在这种情况下调试。
谢谢。
英文:
I have a Task that needs to continuously poll devices for information, so I created the Task in the constructor.
public DeviceManager()
{
Task.Run(Polling);
}
private Func<Task> Polling()
{
return async () =>
{
while (true)
{
await GetInfo();
await Task.Delay(60 * 1000);
}
}
}
I usually run dotnet watch --no-hot-reload to test my program, but now I want to debug it.
However, when the debugger is running, it hangs in this while loop.
Please let me know why I cannot debug in this situation.
Thanks.
答案1
得分: 1
这项任务从未存储在任何地方,因此在被安排执行之前,它可能已被垃圾回收。事实上,除非DeviceManager
是一个单例,否则类本身可能会在生成它的请求完成后立即被垃圾回收。任务不是线程,它代表将来需要完成的一些工作。如果任务本身在被安排之前变成孤立状态,工作就会丢失。
在ASP.NET Core中创建后台服务是通过实现IHostedService
接口来完成的。这在ASP.NET Core中使用托管服务进行后台任务中有描述。该文章展示了定期服务(轮询服务)和排队作业服务的示例。
定时后台服务非常简单,使用定时器定期调用其DoWork
方法:
public class TimedHostedService : IHostedService, IDisposable
{
private int executionCount = 0;
private readonly ILogger<TimedHostedService> _logger;
private Timer? _timer = null;
public TimedHostedService(ILogger<TimedHostedService> logger)
{
_logger = logger;
}
private void DoWork(object? state)
{
var count = Interlocked.Increment(ref executionCount);
_logger.LogInformation(
"Timed Hosted Service is working. Count: {Count}", count);
}
public Task StartAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Timed Hosted Service running.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Timed Hosted Service is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
StartAsync
和StopAsync
方法由ASP.NET Core主机调用以启动和停止服务。在这种情况下,它们只需要启动和停止计时器。
英文:
The task is never stored anywhere so it's probably garbage-collected before it ever has a chance to get scheduled for execution. In fact, unless DeviceManager
is a Singleton, the class itself may get garbage-collected as soon as the request that spawned it completes. A Task isn't a thread, it represents some work that needs to complete in the future. If the task itself gets orphaned before it gets scheduled, the work is lost.
Creating background services in ASP.NET Core is done by implementing the IHostedService interface. This is described in Background tasks with hosted services in ASP.NET Core. That article shows both a poll service and a queued job service example.
The timed background service is pretty simple and uses a timer to call its DoWork
method periodically:
public class TimedHostedService : IHostedService, IDisposable
{
private int executionCount = 0;
private readonly ILogger<TimedHostedService> _logger;
private Timer? _timer = null;
public TimedHostedService(ILogger<TimedHostedService> logger)
{
_logger = logger;
}
private void DoWork(object? state)
{
var count = Interlocked.Increment(ref executionCount);
_logger.LogInformation(
"Timed Hosted Service is working. Count: {Count}", count);
}
public Task StartAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Timed Hosted Service running.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Timed Hosted Service is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
The StartAsync
and StopAsync
are called by the ASP.NET Core host to start and stop the service. In this case all they have to do is start and stop the timer.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论