32

Tôi nhầm lẫn về sự khác biệt giữa việc gửi các mục qua Post() hoặc SendAsync(). Sự hiểu biết của tôi là trong mọi trường hợp khi một mục đạt đến bộ đệm đầu vào của một khối dữ liệu, điều khiển được trả về ngữ cảnh gọi, đúng không? Vậy tại sao tôi lại cần SendAsync? Nếu giả định của tôi là không đúng thì tôi tự hỏi, ngược lại, tại sao bất cứ ai sẽ sử dụng Post() nếu toàn bộ ý tưởng sử dụng các khối dữ liệu là thiết lập một môi trường đồng thời và không đồng bộ.TPL Dataflow, sự khác biệt chức năng giữa Post() và SendAsync() là gì?

Tôi hiểu tất nhiên sự khác biệt về mặt kỹ thuật trong bài viết đó() trả về một bool trong khi SendAsync trả về một nhiệm vụ đang chờ của bool. Nhưng những gì có ý nghĩa gì? Khi nào sự trở lại của một bool (mà tôi hiểu là một xác nhận cho dù mục đã được đặt trong hàng đợi của khối dữ liệu hay không) bao giờ bị trì hoãn? Tôi hiểu ý tưởng chung của khung công tác đồng bộ async/await nhưng ở đây nó không có ý nghĩa gì cả bởi vì khác với bool kết quả của bất kỳ thứ gì được thực hiện cho mục được chuyển vào không bao giờ được trả về người gọi mà thay vào đó được đặt trong "out-queue" và được chuyển tiếp đến các khối dữ liệu được liên kết hoặc bị loại bỏ.

Và có sự khác biệt về hiệu suất giữa hai phương pháp khi gửi các mục không?

Trả lời

39

Để thấy sự khác biệt, bạn cần một tình huống trong đó các khối sẽ hoãn thông báo của họ. Trong trường hợp này, Post sẽ trả lại false ngay lập tức, trong khi SendAsync sẽ trả lại một Task sẽ được hoàn thành khi khối quyết định việc cần làm với thư. Task sẽ có kết quả true nếu thông báo được chấp nhận và kết quả là false nếu không.

Một ví dụ về tình huống trì hoãn là tham gia không tham lam.Một ví dụ đơn giản hơn là khi bạn đặt BoundedCapacity:

[TestMethod] 
public void Post_WhenNotFull_ReturnsTrue() 
{ 
    var block = new BufferBlock<int>(new DataflowBlockOptions {BoundedCapacity = 1}); 

    var result = block.Post(13); 

    Assert.IsTrue(result); 
} 

[TestMethod] 
public void Post_WhenFull_ReturnsFalse() 
{ 
    var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); 
    block.Post(13); 

    var result = block.Post(13); 

    Assert.IsFalse(result); 
} 

[TestMethod] 
public void SendAsync_WhenNotFull_ReturnsCompleteTask() 
{ 
    // This is an implementation detail; technically, SendAsync could return a task that would complete "quickly" instead of already being completed. 
    var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); 

    var result = block.SendAsync(13); 

    Assert.IsTrue(result.IsCompleted); 
} 

[TestMethod] 
public void SendAsync_WhenFull_ReturnsIncompleteTask() 
{ 
    var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); 
    block.Post(13); 

    var result = block.SendAsync(13); 

    Assert.IsFalse(result.IsCompleted); 
} 

[TestMethod] 
public async Task SendAsync_BecomesNotFull_CompletesTaskWithTrueResult() 
{ 
    var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); 
    block.Post(13); 
    var task = block.SendAsync(13); 

    block.Receive(); 

    var result = await task; 
    Assert.IsTrue(result); 
} 

[TestMethod] 
public async Task SendAsync_BecomesDecliningPermanently_CompletesTaskWithFalseResult() 
{ 
    var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); 
    block.Post(13); 
    var task = block.SendAsync(13); 

    block.Complete(); 

    var result = await task; 
    Assert.IsFalse(result); 
} 
+0

ok nhưng đưa ra lời giải thích của bạn, thì logic đằng sau 'Nhiệm vụ ' là gì? Nếu nó không thể gửi ngay lập tức do hoãn nhưng nhiệm vụ hoàn thành sau đó whats sự khác biệt giữa bool là đúng và sai? –

+1

Khối cuối cùng có thể quyết định từ chối thông báo đó (ví dụ: nếu bạn 'Hoàn thành 'khối), trong trường hợp đó kết quả của tác vụ sẽ là' false'. Xem câu trả lời được cập nhật. –

+0

tuyệt vời, điều này bây giờ làm cho cảm giác hoàn toàn, khả năng đó hoàn toàn trượt tâm trí của tôi. Cảm ơn rất nhiều. –

7

Tài liệu làm cho IMO rõ ràng, hợp lý. Cụ thể, đối với Post:

Phương pháp này sẽ trở lại khi khối mục tiêu quyết định chấp nhận hoặc từ chối mục, nhưng không chờ cho mục đó thực sự được xử lý.

Và:

Đối với khối mục tiêu hỗ trợ hoãn thông điệp đưa ra, hoặc cho các khối có thể làm chế biến hơn trong việc thực hiện Post của họ, xem xét sử dụng SendAsync, mà sẽ trở lại ngay lập tức và sẽ cho phép các mục tiêu trì hoãn thông báo đã đăng và sau đó tiêu thụ nó sau khi trả về SendAsync.

Nói cách khác, trong khi cả hai đều không đồng bộ đối với chế biến thông điệp với, SendAsync cho phép khối mục tiêu để quyết định có hay không để chấp nhận thông điệp không đồng bộ quá.

Nghe có vẻ như SendAsync là phương pháp "không đồng bộ" thường xuyên hơn và có thể được khuyến khích nói chung. Những gì không phải là rõ ràng với tôi là lý do tại sao cả hai đều được yêu cầu, vì nó chắc chắn có vẻ như Post là tương đương rộng rãi khi sử dụng SendAsync và sau đó chỉ cần chờ kết quả.

+0

cảm ơn, nó làm cho nó rõ ràng hơn mặc dù câu cuối cùng của bạn tổng kết sự nhầm lẫn còn lại của tôi. Từ các thử nghiệm của riêng tôi, khi một khối dữ liệu từ chối chấp nhận một thông báo, tôi không thấy bất kỳ lợi thế nào khi sử dụng SendAsync qua Bài đăng, cả hai đều không cố gắng gửi lại thông báo khi khối dữ liệu báo hiệu rằng nó chấp nhận tin nhắn sau này. (cả hai ngay lập tức trở lại nếu tin nhắn bị từ chối và cả hai ngay lập tức trở lại nếu tin nhắn được chấp nhận). Trong đó ngữ nghĩa của "chấp nhận" tin nhắn gửi lại vs SendAsync vẫn còn nebulous với tôi. –

+0

Tôi đoán tôi chỉ không hiểu có bao nhiêu độ trễ có khả năng được giới thiệu trong cơ chế "chấp nhận/từ chối" của các thư mới được truyền. Cho đến nay tôi chưa bao giờ thấy bất kỳ sự chậm trễ có thể đo lường giữa việc đi qua và sự xuất hiện của một thông điệp trong hàng đợi đầu vào/từ chối từ hàng đợi. Nhưng cảm ơn anyway cho việc tập trung vào phần "chấp nhận/từ chối" của vấn đề. –

+3

@Freddy: Chắc chắn - nhưng sự khác biệt là khi một khối * trì hoãn * quyết định chấp nhận/từ chối. Có lẽ khối mục tiêu bạn đang sử dụng không bao giờ làm điều đó, tất nhiên. –