2015-02-04 11 views
8

Aşağıdaki kodları izlemeyi deniyorum, iki parçadan oluşuyor, biri prizma yoluyla geziniyor. Gezinmeye izin verildiğinde, derin bir zaman uyumsuz olarak ancak her defasında yeni bir bağlamla başlıyorum.UOW - Bir önceki asenkron işlem tamamlanmadan önce bu bağlamda ikinci bir işlem başlatıldı

public void OnNavigatedTo(NavigationContext navigationContext) 
{ 
    int relatieId = (int)navigationContext.Parameters["RelatieId"]; 
    if (_relatie != null && _relatie.RelatieId == relatieId) return; 

    loadRelatieAsync(relatieId); 
} 

public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback) 
{ 
    bool navigationAllowed = true; 
    continuationCallback(navigationAllowed); 
} 
burada herhangi bir sorun: Daha sonra kodunda Öyle iptal sonra ;-)

navigasyon mantık meselesidir bu yüklemeyi bitirmedi ama aşağıdaki kod bile yaramayan gezinmeleri bekleyen iptal etmek isteyeyim

derin yükleme mantığı: Ben bekliyor unuttum sanki

private async Task loadRelatieAsync(int relatieId) 
{ 
    try 
    { 
     await Task.Run(async() => 
     { 

      _unitOfWork = _UnitOfWorkFactory.createUnitOfWorkAsync(); 

      IEnumerable<Relatie> relaties = await getRelatieAsync(_unitOfWork, relatieId).ConfigureAwait(true); 

      _relatieTypeTypes = await getRelatieTypeTypesAsync(_unitOfWork, relatieId).ConfigureAwait(true); 
      _relatie = relaties.FirstOrDefault(); 

      _unitOfWork.Dispose(); 
     }).ConfigureAwait(true); 

     processRelatie(_relatie); 

     processRelatieTypes(_relatie, _relatieTypeTypes); 
    } 
    catch (Exception Ex) 
    { 

     MessageBox.Show(Ex.Message); 
     throw; 
    } 

} 

private async Task<IEnumerable<Relatie>> getRelatieAsync(IUnitOfWorkAsync unitOfWork, int relatieId) 
{ 

    IEnumerable<Relatie> relaties = null; 
    try 
    { 
     IRepositoryAsync<Relatie> relatieRepository = unitOfWork.RepositoryAsync<Relatie>(); 
     relaties = await relatieRepository 
      .Query(r => r.RelatieId == relatieId) 
      .Include(i => i.BegrafenisOndernemer) 
      .SelectAsync() 
      .ConfigureAwait(false); 

     IRepositoryAsync<Adres> adresRepository = unitOfWork.RepositoryAsync<Adres>(); 
     //exception is thrown after executing following line 
     var adressen = await adresRepository 
      .Query(r => r.RelatieId == relatieId) 
      .Include(i => i.AdresType) 
      .SelectAsync() 
      .ConfigureAwait(false); 
     _relatieTypeRepository = unitOfWork.RepositoryAsync<RelatieType>(); 
     var relatieTypes = await _relatieTypeRepository 
      .Query(r => r.RelatieId == relatieId) 
      .SelectAsync() 
      .ConfigureAwait(false); 
    } 
    catch (Exception Ex) 
    { 
     MessageBox.Show(Ex.Message);//exception is shown here 
     throw; 
    } 
    return relaties; 
} 

private async Task<IEnumerable<RelatieTypeType>> getRelatieTypeTypesAsync(IUnitOfWorkAsync unitOfWork, int relatieId) 
{ 

    IEnumerable<RelatieTypeType> relatieTypeTypes = null; 
    try 
    { 
     IRepositoryAsync<RelatieTypeType> relatieTypeTypeRepository = 
      unitOfWork.RepositoryAsync<RelatieTypeType>(); 

     relatieTypeTypes = await relatieTypeTypeRepository 
      .Query() 
      .SelectAsync() 
      .ConfigureAwait(false); 

    } 
    catch (Exception Ex) 
    { 
     MessageBox.Show(Ex.Message); 
     throw; 
    } 
    return relatieTypeTypes; 
} 

ben alıyorum istisnaları tutmak, ancak bu durum asla. Ayrıca GUI iş parçacığına devam etmek istediğimde configureawait (true) özelliğini de kullanıyorum. Ama bu hatayı deeploading mantığında alıyorum. İş ve depo sınıfları birimi aynı zamanda async bekleme mekanizmasını kullanır, fakat orada da doğru şekilde bekliyorum.

Bir önceki asenkron işlem tamamlanmadan önce bu bağlamda ikinci bir işlem başlatıldı. Bu bağlamda başka bir yöntem aramadan önce tüm zaman uyumsuz işlemlerin tamamlandığından emin olmak için 'bekle' seçeneğini kullanın. Herhangi bir üye üyenin iş parçacığı güvenli olduğu garanti edilmez.

Düzenleme Bu muhtemelen cevap, ancak kodu üzerinde genel bir görünüm

+0

, createUnitOfWorkAsync() öğesinin eşzamansız bir yöntem olmadığını lütfen unutmayın. Sadece async bekleme paradigmasını destekleyen bir sınıf oluşturur. –

+1

'createUnitOfWorkAsync' bir * yeni * bağlamı yaratıyor, doğru mu? –

+1

'ConfigureAwait (true);' Bu ilk zamanlayıcıdır .. –

cevap

12

sorunun bu kodudur. Halihazırda yürütmekte olan senaryo, daha sonra üzerine yazıldığından, yeni UnitOfWork'u kullanır. Dikkat edilmesi kolay değil, ancak basit bir yarış durumu. Tüm örnek değişkenleri yerel değişkenlere göre değiştirerek buldum ve sonra sorun reddedildi.

0

(kaldırıldı logger kod kod boyutunu azaltmak için).

Async/await'in asıl amacı, geçerli Thread'i korumaktır. Bu, UI Thread'i engellememeye ve Uygulamanıza yanıt vermemeye yardımcı olur.

Zaten derin yüklemenizin bir ThreadPool iş parçacığında gerçekleştiğinden emin olun, çünkü tamamen Task.Run(). Yükleme mekanizmanızda varsayılan senkronize EntityFramework yöntemlerini kullanarak sorunlarınızın çoğunu alabilirsiniz.

İlk bakışta, kodunuz async çağrılarından itibaren ince görünüyor. Belki de derin yüklemeniz defalarca tetiklenir? senaryo yeni bir örneği ile yazılır bir kez başladığında

_unitOfWork = _UnitOfWorkFactory.createUnitOfWorkAsync(); 

IEnumerable<Relatie> relaties = await getRelatieAsync(_unitOfWork, relatieId).ConfigureAwait(true); 

_relatieTypeTypes = await getRelatieTypeTypesAsync(_unitOfWork, relatieId).ConfigureAwait(true); 
_relatie = relaties.FirstOrDefault(); 

_unitOfWork.Dispose(); 

UnitOfWork, bir örnek değişkenidir:

+0

Yorum için teşekkür ederim, bu şekilde yapıyorum çünkü bir iptal belirteci kullanarak işlemi bir sonraki arttırmada iptal edebilmek istiyorum. loadRelatieAsync yöntemi birden çok kez çağrılır ve aynı anda hiç bir iptal olmadığından eşzamanlı olarak çalışır, ancak bu her zaman farklı bir bağlam kullanıyorum çünkü bu önemli olmamalıdır. Tek yapılı yaratılışın altında yaratılmıştır. Şu an GUI iş parçacığı engellemeyi kaldırmaya çalışıyorum ama beklemedeki gezinme işlemini iptal etmek istiyorum –

+0

Yalnızca işlemleriniz arasındaki iptal isteklerini kontrol edebilirsiniz, bu da hiçbir değişiklik yapmaz. –

+0

Neden sadece bir yükleme işlemi zaten başlatılmış ve eğer varsa, bu görevi iade edip etmediğinizi kontrol etmiyorsunuz? Ayrıca içeriğiniz hakkında% 100 emin misiniz? Çünkü devam eden işlemler hata yaptığınızda, büyük olasılıkla problemdir. –

İlgili konular