2015-01-28 17 views
5

Vâng, vấn đề của tôi là gọi đang đợi bảng.ExecuteAsync (...) trên Azure Storage Table sẽ chèn dữ liệu được yêu cầu, nhưng không bao giờ kết thúc (không trả lại TableResult). Trường hợp tương tự với các hoạt động InsertOrUpdate và Update. Tôi cũng đã thử các bảng khác nhau với số lượng thuộc tính khác nhau - cùng một vấn đề.Bàn lưu trữ Azure: Đang đợi bảng.ExecuteAsync (ChènOperation) thực hiện, nhưng không bao giờ kết thúc

Khi tôi gọi bảng.Execute (...) - mọi thứ hoạt động tốt cho mọi loại hoạt động.

Dưới đây là mã của tôi - đơn giản như vậy:

gọi Outer (nó được đặt trong MVC Controller trong hành động async):

List<Task<ServiceResult<Boolean?>>> addPostTasks = new List<Task<Common.ServiceResult<bool?>>>();    
foreach (var userStream in userStreams) 
{ 
    Task<ServiceResult<Boolean?>> addPostTask = postsStorageSvc.AddImagePost(...); 
    postsAddImagePostTasks.Add(addPostTask); 
} 
Task.WaitAll(addPostTasks.ToArray()); 

Cách gọi:

public async Task<ServiceResult<Boolean?>> AddImagePost(...) 
{ 
ServiceResult<Boolean?> result = new ServiceResult<bool?>(null); 
try 
{ 
    PostTableEntity newPost = new PostTableEntity(streamId.ToString(), Guid.NewGuid().ToString(), creatorId, date, htmlText);    
    TableOperation insertOperation = TableOperation.Insert(newPost); 
    //Following line never ends! 
    TableResult tableResult = await this._storageTableBootstrapper.Table.ExecuteAsync(insertOperation);     
    //Following line works perfect - but is not ASYNC 
    TableResult tableResult = this._storageTableBootstrapper.Table.Execute(insertOperation); 
} 
catch (Exception ex) 
{ 
    result.Result = false; 
    result.Errors.Add("AzurePostsStorageService Unexpected error: " + ex.Message); 
} 
return result; 
} 
+0

Bạn gọi phương thức này bằng cách nào? –

+0

Ý của bạn là gì? Khối mã này có trong phương thức không đồng bộ, tôi đang cập nhật câu hỏi của mình để hiển thị các đường xung quanh. –

+0

Hiển thị chữ ký phương thức và cách bạn gọi nó. Bạn có thể chặn nó bằng cách sử dụng 'Task.Result' hoặc' Task.Wait'? –

Trả lời

9

Vấn đề là ở đây:

Task.WaitAll(addPostTasks.ToArray()); 

phương pháp async của bạn cố gắng sắp xếp bản thân trở lại Ngữ cảnh đồng bộ hóa ASP.NET, bị kẹt vì bạn đã bắt đầu cuộc gọi chặn bằng cách sử dụng Task.WaitAll.

Thay vào đó, bạn sẽ cần phải làm theo các async tất cả các cách mô hình và sử dụng Task.WhenAll, và await trên rằng:

await Task.WhenAll(addPostTasks.ToArray); 

Stephan Cleary trau chuốt về vấn đề này trong bài viết trên blog của mình (mà @NedStoyanov thêm):

một điểm quan trọng khác: một bối cảnh ASP.NET yêu cầu là không gắn với một chủ đề cụ thể (như bối cảnh UI là), nhưng nó chỉ cho phép một chủ đề cùng một lúc. Khía cạnh thú vị này không chính thức là được ghi lại ở bất kỳ đâu AFAIK, nhưng nó được đề cập trong bài viết MS2 về SynchronizationContext của tôi.

+2

Thông tin tốt về ngữ cảnh ASP, điều cần biết. –

4

Đây là một cổ điển deadlock do dòng này:

Task.WaitAll(addPostTasks.ToArray()); 

hãy thử thay đổi nó để:

await Task.WhenAll(addPostTasks.ToArray()); 

Về cơ bản các các Task.WaitAll khối thread yêu cầu và nó là không thể thực hiện việc tiếp tục các Tasks khởi xướng bởi await table.ExecuteAsync(...). Một cách khác là sử dụng ConfigureAwait(false) về các tác vụ nội bộ của bạn để tránh chuyển đổi SynchronizatonContext.

await table.ExecuteAsync(...).ConfigureAwait(false); 

Bạn có thể sử dụng ConfigureAwait(false) bất cứ khi nào bạn không cần chuyển sang gốc SynchronizationContext. Trong trường hợp của bạn tôi tin rằng bạn có thể làm điều đó với tất cả đang chờ đợi như bạn đang ở trên máy chủ và nó không quan trọng nếu mã sau khi await thực hiện trên hồ bơi thread hay không.

Xem bài viết này để biết thêm chi tiết: msdn.microsoft.com/enus/magazine/jj991977.aspx

+0

Câu trả lời của bạn có ý nghĩa tương tự như câu hỏi trên, tuy nhiên bạn ở đâu Yuval Itzchakov đã cung cấp thêm thông tin. –

+0

Vâng, câu trả lời của anh ta tốt hơn. Tôi cũng học được điều gì đó. –

+0

OK, vì vậy hãy rõ ràng và hiểu rõ hơn về trường hợp. ** Bạn có khuyến cáo sử dụng ".ConfigureAwait (false)" trên tất cả các hoạt động không đồng bộ của chúng tôi đang ở trên cùng của chồng thực hiện ** (như table.ExecuteAsync (...) hoặc thậm chí các hoạt động/phương thức không đồng bộ của riêng chúng tôi) không? –

Các vấn đề liên quan