2013-05-31 46 views
1

我必須從Azure加載一些對象。我計劃在5,以花費更少的時間(一種懶加載)來加載它們五:開始未執行

ProductManager.LoadProduct叫我ProductAccess.LoadProduct從蔚藍 這最後的方法裝載的產品,然後爲了引發一個事件經理可以獲得產品。然後,如果它收到產品,則會再次調用ProductAccess.LoadProduct。 etc ....

無法使用await/async,因爲它是跨平臺代碼(monodroid/monotouch穩定版本還沒有await/async)。

第一次加載是正確的,然後第二次調用的作品,但似乎我的任務沒有執行(開始不執行我的第二個任務...)。我檢查線程號,第二次,Task.Factory.StartNew(()=>在主線程上執行,我試圖通過指定長時間運行來修復它,但仍然不起作用

這裏是我的代碼:

經理方:

public void LoadProduct() 
{ 
    ProductAccess.LoadProductsAsync() 
} 

public void receiveProductsAsync(Object pa, EventArgs e) 
{ 
    if (((ProductEventArgs)e).GetAttribute.Equals("LoadProductsAsync")) 
    { 
     IoC.Resolve<IProductAccess>().RequestEnded -= receiveProductsAsync; 

     if (((ProductEventArgs)e).LP).Count() != 0)      
      LoadProductsAsync(); 

     Products = Products.Concat(((ProductEventArgs)e).LP).ToList(); 
     if (((ProductEventArgs)e).E != null) 
     { 
      if (RequestEnded != null) 
       RequestEnded(this, new OperationEventArgs() { Result = false, E = ((ProductEventArgs)e).E, GetAttribute = "LoadProductsAsync" }); 
     } 
     else 
     { 
      if (RequestEnded != null) 
      { 
       RequestEnded(this, new OperationEventArgs() { Result = true, GetAttribute = "LoadProductsAsync" }); 
      } 
     } 
    } 
} 

接入側:

public void LoadProductsAsync() 
{ 
    Task<ProductEventArgs>.Factory.StartNew(() => 
    { 
     var longRunningTask = new Task<ProductEventArgs>(() => 
     { 
      try 
      { 
       var _items = this.table.Select(x => new Product(.....)).Skip(nbrProductLoaded).Take(nbrProductToLoadAtEachTime).ToListAsync().Result; 
       this.nbrProductLoaded += _items.Count(); 
       Task.Factory.StartNew(() => synchronizeFavorite(_items)); 
       return new ProductEventArgs() { LP = _items, GetAttribute = "LoadProductsAsync" }; 
      } 
      catch (Exception e) 
      { 
       return new ProductEventArgs() { E = e, GetAttribute = "LoadProductsAsync" }; 
      } 
     }, TaskCreationOptions.LongRunning); 

     longRunningTask.Start(); 

     if (longRunningTask.Wait(timeout)) 
      return longRunningTask.Result; 

     return new ProductEventArgs() { E = new Exception("timed out"), GetAttribute = "LoadProductsAsync" }; 

    }, TaskCreationOptions.LongRunning).ContinueWith((x) => { 
     handleResult(x.Result); 
    }, TaskScheduler.FromCurrentSynchronizationContext()); 
} 

回答

1

Task.Factory.StartNew將默認使用當前TaskScheduler

第一次,你沒有在一個任務中運行,所以當前的TaskScheduler是默認的TaskScheduler(它將運行在線程池中)。

當您通過使用TaskScheduler.FromCurrentSynchronizationContexthandleResult安排回原始上下文時,它將在主線程的任務內運行handleResult。所以在這種情況下,當前的TaskScheduler是UI TaskScheduler,而不是默認的TaskScheduler

要修復此問題,請明確將TaskScheduler.Default傳遞給您想要在線程池線程上運行的任何StartNew(並刪除LongRunning)。

+0

感謝它的作品,感謝您的非常明確的解釋! – Dahevos