2014-09-05 14 views
5

tôi có mã ví dụ này:ContinueWith Chaining không làm việc như mong đợi

static void Main(string[] args) { 
     var t1 = Task.Run(async() => { 
      Console.WriteLine("Putting in fake processing 1."); 
      await Task.Delay(300); 
      Console.WriteLine("Fake processing finished 1. "); 
     }); 
     var t2 = t1.ContinueWith(async (c) => { 
      Console.WriteLine("Putting in fake processing 2."); 
      await Task.Delay(200); 
      Console.WriteLine("Fake processing finished 2."); 
     }); 
     var t3 = t2.ContinueWith(async (c) => { 
      Console.WriteLine("Putting in fake processing 3."); 
      await Task.Delay(100); 
      Console.WriteLine("Fake processing finished 3."); 
     }); 
     Console.ReadLine(); 
    } 

Giao diện điều khiển đầu ra baffles tôi:

  • Đưa vào chế biến giả 1.
  • chế biến Fake xong 1.
  • Đưa vào chế biến giả 2.
  • Đưa vào chế biến giả 3.
  • xử lý
  • Fake xong 3.
  • chế biến Fake xong 2.

Tôi cố gắng để chuỗi nhiệm vụ để họ thực hiện cái khác, những gì tôi làm sai? Và tôi không thể sử dụng chờ đợi, đây chỉ là mã ví dụ, trong thực tế, tôi đang xếp hàng các tác vụ đến (một số không đồng bộ, một số không) và muốn thực thi chúng theo thứ tự mà chúng đến nhưng không có song song, ContinueWith có vẻ tốt hơn việc tạo một ConcurrentQueue và xử lý everythning bản thân mình, nhưng nó chỉ không hoạt động ...

+0

tuyên bố chờ đợi "chia tách" tác vụ. Vì vậy, t1 chỉ tham khảo nửa đầu. Tôi ngạc nhiên Đưa vào xử lý giả 2 không xảy ra ngay lập tức sau khi đưa vào xử lý giả 1 –

+0

@WeylandYutani Tôi giải thích trong câu trả lời của tôi tại sao điều đó không xảy ra. – Servy

+0

thực sự tôi đang nói rác một lần nữa vì vậy bỏ qua tôi –

Trả lời

8

Hãy xem loại t2. Đó là Task<Task>. t2 sẽ được hoàn thành khi hoàn tất bắt đầu tác vụ thực hiện công việc thực tế không khi công việc đó thực sự kết thúc.

Thay đổi nhỏ nhất đối với mã của bạn để mã hoạt động sẽ là thêm unwrap sau cả cuộc gọi thứ hai và thứ ba của bạn tới ContinueWith, để bạn hoàn thành công việc.

Giải pháp thành ngữ đơn giản hơn là chỉ cần xóa hoàn toàn các cuộc gọi ContinueWith và chỉ sử dụng await để thêm tiếp tục vào tác vụ.

Điều thú vị là đủ, bạn sẽ thấy những hành vi tương tự cho t1 nếu bạn sử dụng Task.Factory.StartNew, nhưng Task.Run được thiết kế đặc biệt để làm việc với async lambdas và thực sự trong nội bộ unwraps tất cả Action<Task> đại biểu để trả lại kết quả của nhiệm vụ trở về, chứ không phải là một nhiệm vụ đại diện cho việc bắt đầu nhiệm vụ đó, đó là lý do tại sao bạn không cần phải bỏ qua nhiệm vụ đó.

+0

Cảm ơn bạn, Unwrap hoạt động (không thể sử dụng chờ đợi vì mã thực không phải là danh sách tuyến tính, tôi nhận được một luồng công việc để thực thi serially, vì vậy chúng cần được xếp hàng đợi.)). –

+0

@MartinSykora Có, bạn * có thể * sử dụng 'await' thay vì' ContinueWith', mặc dù thật khó để chỉ cho bạn cách mà không biết chi tiết về tình huống của bạn. Rất có thể bạn chỉ đơn giản là có thể viết một phương thức 'async' chấp nhận một nhiệm vụ, chờ đợi nó, cùng với chờ đợi những thứ khác và gọi các phương thức khác, và sau đó trả về một 'Task'. Khá nhiều lần bạn đang gọi 'ContinueWith' trên một nhiệm vụ mà bạn có thể gọi là 'await' trên nó thay vào đó và nó trở nên đẹp hơn, chỉ với những ngoại lệ hiếm hoi. – Servy

2

trong thực tế tôi đang xếp hàng nhiệm vụ đến (một số không đồng bộ, một số không) và muốn thực hiện chúng theo thứ tự họ bước vào nhưng không có lý song song

Bạn có thể muốn sử dụng TPL Dataflow cho cái đó. Cụ thể, ActionBlock.

var block = new ActionBlock<object>(async item => 
{ 
    // Handle synchronous item 
    var action = item as Action; 
    if (action != null) 
    action(); 

    // Handle asynchronous item 
    var func = item as Func<Task>; 
    if (func != null) 
    await func(); 
}); 

// To queue a synchronous item 
Action synchronous =() => Thread.Sleep(1000); 
block.Post(synchronous); 

// To queue an asynchronous item 
Func<Task> asynchronous = async() => { await Task.Delay(1000); }; 
blockPost(asynchronous); 
+0

Đẹp, đó có thể chỉ là những gì tôi cần nếu nó hoạt động, chắc chắn sẽ thanh lịch hơn :-) –

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