0

我刚刚修复了一些生产代码,但没有按预期工作。我们正在讨论用 C# 编写的 .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 触发。

4

1 回答 1

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.");
于 2014-10-29T09:27:58.210 回答