2014-10-29 65 views
0

我只是修復了一些生產代碼,那是不能按預期工作。我們正在討論用C#編寫的.NET 4.5.1中的Windows服務。雖然它是固定的,但我試圖理解發生了什麼。一些谷歌搜索沒有在這方面顯示太多的結果。一個任務開始如下:Task.Factory.StartNew需要lambda/Action?

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

據我所知,在線程中,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觸發。

+0

你可以給'StartNew'使用更多的上下文嗎?我們是否也可以看到「DoSomeWork」的主體? – Gusdor 2014-10-29 09:01:35

+0

你的意思是不按預期工作?這兩個代碼片段做同樣的事情。 – 2014-10-29 09:10:05

+0

準確地說,我也希望這兩種方法都能正常工作,但第一種方法沒有辦法,我不知道爲什麼。 – Paul 2014-10-29 09:14:40

回答

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

感謝您對此的見解。我將進一步調查這一點,因爲我需要Wait()來防止同時運行多個tmes的方法。另外,我使用SimpleInjector,UnitOfWork由Entity Framework 6.0.2支持。請原諒我缺乏初始信息。 – Paul 2014-10-29 09:35:55

+0

此外,啓動任務的方法正在由主線程上的Timer對象觸發。 – Paul 2014-10-29 09:37:42

+1

「等待」不可能阻止該方法同時執行 - 它不是「鎖定」。你正在使用什麼'Timer'類?我編輯了一個同時運行的解決方案 – Gusdor 2014-10-29 09:46:26

相關問題