2016-02-25 15 views
5

Tôi cố gắng để asynchronize mã ban đầu của tôiChạy nhiệm vụ bó async khi một trật tự thực hiện nhất định cần phải được bảo tồn

for(var item in items) 
{ 
    dbAccess.Save(item); 
} 

mà hoạt động tốt:

var tasks = new List<Task>(); 

    for(var item in items) 
    { 
     tasks.Add(dbAccess.SaveAsync(item)); 
    } 

    await Task.WhenAll(tasks); 

Tuy nhiên, tôi cần thêm một cuộc gọi dọn sạch bổ sung trước khi tôi lưu và lưu vào DB của tôi:

var tasks = new List<Task>(); 

    for(var item in items) 
    { 
     tasks.Add(dbAccess.DeleteAsync(item.id)); 
     tasks.Add(dbAccess.SaveAsync(item)); 
    } 

    await Task.WhenAll(tasks); 

Mã này ở trên không chính xác vì Lưu ync không nên được thực hiện cho đến khi DeleteAsync tương ứng được hoàn tất. Nói cách khác, việc xóa phải luôn đi trước khi lưu cho từng mục nhưng thứ tự cho các mục không quan trọng.

Có cách nào hoàn hảo để thực hiện việc này không?

+1

Làm thế nào về việc phát hành tất cả các xóa trước, chờ chúng, sau đó phát hành tất cả các lưu và sau đó chờ đợi cho những người? Nếu không, bạn nên đóng gói mỗi lần xóa + lưu vào một tác vụ duy nhất. –

+0

Lasse điểm tốt, tôi đơn giản hóa mã của tôi cho mục đích của câu hỏi này. Tôi không thể thực hiện đề xuất của bạn vì có nhiều hơn một chút tôi không hiển thị. Trên thực tế, DeleteAsync trả về một thứ khác cần được chuyển đến SaveAsync. – AstroSharp

+0

Vì vậy? Gói chúng thành một nhiệm vụ mà trước tiên gọi deleteasync, sau đó gọi saveasync sau đó? –

Trả lời

6

Tạo một phương pháp async mà thực hiện việc xóa, sau đó có một pha cứu cho một mục duy nhất, và thực hiện tất cả những hoạt động hợp trên mỗi mục trong song song:

var tasks = items.Select(async item => 
{ 
    await dbAccess.DeleteAsync(item.id); 
    await dbAccess.SaveAsync(item); 
}); 
await Task.WhenAll(tasks); 
2

Bạn có thể sử dụng một Func<Task> để đóng gói hai async cuộc gọi vào một đơn Task như thế này:

for(var item in items) 
{ 
    //We store the value of item in a local variable 
    //because it is not recommended to close over a loop variable 
    var my_item = item; 

    Func<Task> task_fact = async() => 
    { 
     await dbAccess.DeleteAsync(my_item.id); 
     await dbAccess.SaveAsync(my_item); 
    }; 

    tasks.Add(task_fact()); 
} 

này sẽ tạo ra một nhiệm vụ mà các cuộc gọi phương pháp xóa, không đồng bộ chờ đợi cho nó, và sau đó gọi là tiết kiệm và chờ đợi không đồng bộ.

Bạn có thể làm điều tương tự bằng phương pháp.

1

Làm thế nào về việc sử dụng ContinueWith:

var tasks = new List<Task>(); 

for(var item in items) 
{ 
    var task = dbAccess.DeleteAsync(item.id) 
      .ContinueWith(antecedent => dbAccess.SaveAsync(item)) 
      .Unwrap(); 

    tasks.Add(task); 
} 

await Task.WhenAll(tasks); 
+0

Bạn cần phải bỏ qua kết quả, vì hiện tại bạn không chờ đợi quá trình lưu hoàn tất. Nó cũng lộn xộn hơn rất nhiều so với việc sử dụng 'await', và có thể không có lỗi xử lý ngữ nghĩa bạn muốn. – Servy

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