Task.Factory.StartNew requires a lambda / Action?
本文关键字:Action lambda Factory StartNew requires Task | 更新日期: 2023-09-27 18:28:25
我刚刚修复了一些生产代码,但没有按预期工作。我们讨论的是用C#编写的.NET 4.5.1中的Windows服务。虽然它是固定的,但我正在努力了解发生了什么。一些谷歌搜索并没有显示太多结果。任务启动如下:
var task = Task.Factory.StartNew(this.SendReminders);
logger.Info("Waiting for sending to complete...");
task.Wait();
据我所知,就像在Threads中一样,StartNew接收到一个对它应该执行的方法的引用。这在调试环境中是有效的,但在生产(Release)中则不然。以下是:
var task = Task.Factory.StartNew(() => this.SendReminders());
logger.Info("Waiting for sending to complete...");
task.Wait();
我在这里错过了什么?代码是否以完全不执行的方式进行了优化?
根据要求,任务主体方法:
internal void SendReminders()
{
using (this.container.BeginLifetimeScope())
{
try
{
var uow = container.GetInstance<UnitOfWork>();
this.logger.Info("Sending reminders..");
var handler = container.GetInstance<IHandleCommand<SendReminderCommand>>();
handler.Handle(new SendReminderCommand());
uow.SaveChanges();
}
catch (Exception ex)
{
this.logger.Exception(ex);
throw;
}
}
}
到目前为止,还没有记录任何异常,并且该服务正在运行。使用Task.Factory.StartNew(this.SendReminders)行在生产中没有启动,但使用lambda就像一种魅力。
我使用的是SimpleInjector,UnitOfWork由EntityFramework6.0.2支持。启动任务的方法由主线程上的Timer触发。
这可能是对Task.Wait
的阻塞调用导致死锁的一个示例。
我不熟悉unity,但像this.container.BeginLifetimeScope()
和container.GetInstance<UnitOfWork>
这样的调用可能会调用回入口线程。发布环境可以使用不同的SynchronizationContext
进行调试。
如果没有行为的工作示例,很难判断,但请尝试删除对Task.Wait
的调用,看看会发生什么!通常认为,在Task
完成后使用continuation来安排工作是一种更好的做法。
//m_RemindersTask is a member of type Task
if(m_RemindersTask != null && m_RemindersTask.Status != TaskStatus.Running) //prevent simultaneous execution
{
m_RemindersTask = Task.Factory.StartNew(() => this.SendReminders());
logger.Info("Waiting for sending to complete...");
task.ContiueWith(p => /*work to be done after the task*/,
TaskScheduler.FromCurrentSynchronizationContext()); //this [optional parameter] makes sure that the continuation is run on the same thread that the scheduling method is run on, if possible.
}
else
//Is Warning the correct method? You get the idea
logger.Warning("Cannot send reminders: reminders are already being sent.");