Dưới đây là một phiên bản đơn giản của mã mà tôi đang gặp sự cố. Khi tôi chạy điều này trong một ứng dụng giao diện điều khiển, nó hoạt động như mong đợi. Tất cả các truy vấn được chạy song song và Task.WaitAll()
trả lại khi tất cả đều hoàn tất.Task.WaitAll treo với nhiều tác vụ có thể chờ đợi trong ASP.NET
Tuy nhiên, khi mã này chạy trong ứng dụng web, yêu cầu chỉ bị treo. Khi tôi đính kèm một trình gỡ lỗi và phá vỡ tất cả, nó cho thấy rằng việc thực hiện được chờ đợi trên Task.WaitAll()
. Và nhiệm vụ đầu tiên đã hoàn thành, nhưng những công việc khác chưa bao giờ kết thúc.
Tôi không thể hiểu tại sao nó treo khi chạy trong ASP.NET, nhưng hoạt động tốt trong một ứng dụng giao diện điều khiển.
public Foo[] DoWork(int[] values)
{
int count = values.Length;
Task[] tasks = new Task[count];
for (int i = 0; i < count; i++)
{
tasks[i] = GetFooAsync(values[i]);
}
try
{
Task.WaitAll(tasks);
}
catch (AggregateException)
{
// Handle exceptions
}
return ...
}
public async Task<Foo> GetFooAsync(int value)
{
Foo foo = null;
Func<Foo, Task> executeCommand = async (command) =>
{
foo = new Foo();
using (SqlDataReader reader = await command.ExecuteReaderAsync())
{
ReadFoo(reader, foo);
}
};
await QueryAsync(executeCommand, value);
return foo;
}
public async Task QueryAsync(Func<SqlCommand, Task> executeCommand, int value)
{
using (SqlConnection connection = new SqlConnection(...))
{
connection.Open();
using (SqlCommand command = connection.CreateCommand())
{
// Set up query...
await executeCommand(command);
// Log results...
return;
}
}
}
+1. Mặc dù tôi sẽ sử dụng thuật ngữ "yêu cầu ngữ cảnh" thay vì "chủ đề chính". –
@StephenCleary Vâng, nó đã gây tranh cãi. Tôi đặt chủ đề chính trong dấu ngoặc kép vì nó không phải là chủ đề chính của toàn bộ ứng dụng, nhưng nó có thể được coi là "chủ đề chính của yêu cầu đó". Đó là một cách suy nghĩ hữu ích về vấn đề trong đầu tôi. – Servy
Một cảnh báo quan trọng là nhiệm vụ chờ đợi.WhenAll sẽ không ném AggregateException; chỉ một trong những ngoại lệ bên trong sẽ được truyền bá. Nếu bạn muốn kiểm tra toàn bộ AggregateException, bạn sẽ cần phải lưu trữ một tham chiếu đến nhiệm vụ được trả về từ task.WhenAll và kiểm tra thuộc tính Exception của nó một cách rõ ràng. –