2013-05-31 56 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