Task.Factory.StartNew需要一个lambda / Action?

时间:2014-10-29 08:57:44

标签: c# reference lambda action taskfactory

我刚刚修改了一些生产代码,但没有按预期工作。我们正在讨论用.NET编写的.NET 4.5.1中的Windows服务。虽然它已经修好了,但我试图了解发生了什么。一些谷歌搜索没有显示出太多的结果。正在开展的任务如下:

var task = Task.Factory.StartNew(this.SendReminders);
 logger.Info("Waiting for sending to complete...");
 task.Wait();

据我所知,在Threads中,StartNew接收对它应该执行的方法的引用。这适用于调试环境,但它不适用于生产(发布)。以下是:

 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正在由Entity Framework 6.0.2支持。启动任务的方法由主线程上的Timer触发。

1 个答案:

答案 0 :(得分:2)

这可能是阻塞调用Task.Wait引起的死锁的一个例子。

我不熟悉统一,但this.container.BeginLifetimeScope()container.GetInstance<UnitOfWork>之类的调用可能会调用回入线程。发布环境可能使用不同的SynchronizationContext进行调试。

如果没有行为的实际示例很难说,但请尝试删除对Task.Wait的调用,看看会发生什么!在Task完成后,使用延续来安排工作通常被认为是更好的做法。

//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.");