2012-09-28 23 views
5

Tôi không chắc chắn nếu điều này là có thể, nhưng nếu có, tôi có lẽ không làm đúng. Giả sử tôi có một bộ đệm dùng chung được liên kết với nhiều người tiêu dùng (ActionBlocks). Mỗi người tiêu dùng nên tiêu thụ dữ liệu thỏa mãn một biến vị ngữ được sử dụng để liên kết nó với bộ đệm. Ví dụ, ActionBlock1 nên tiêu thụ số đáp ứng x => x % 5 == 0, ActionBlock2 nên tiêu thụ chỉ x => x % 5 == 1, vvLiên kết ActionBlocks được tạo động với BufferBlock

Đây là những gì tôi đã có:

private static ITargetBlock<int> BuildPipeline(int NumProductionLines) 
{ 
    var productionQueue = new BufferBlock<int>(); 

    for (int i = 0; i < NumProductionLines; i++) 
    { 
     ActionBlock<int> productionLine = new ActionBlock<int>(num => Console.WriteLine("Processed by line {0}: {1}", i + 1, num)); 

     productionQueue.LinkTo(productionLine, x => x % NumProductionLines == i); 
    } 

    return productionQueue; 
} 

Và sau đó tôi gọi:

Random rnd = new Random(); 

ITargetBlock<int> temp = BuildPipeline(5); 

while (true) 
{ 
    temp.Post(rnd.Next(255)); 
} 

Tuy nhiên điều này không hoạt động. Không có đầu ra nào được hiển thị trong bảng điều khiển. Nếu tôi sửa đổi phương thức BuildPipeline là:

private static ITargetBlock<int> BuildPipeline(int NumProductionLines) 
{ 
    var productionQueue = new BufferBlock<int>(); 

    ActionBlock<int> productionLine1 = new ActionBlock<int>(num => Console.WriteLine("Processed by line {0}: {1}", 1, num)); 
    ActionBlock<int> productionLine2 = new ActionBlock<int>(num => Console.WriteLine("Processed by line {0}: {1}", 2, num)); 
    ActionBlock<int> productionLine3 = new ActionBlock<int>(num => Console.WriteLine("Processed by line {0}: {1}", 3, num)); 
    ActionBlock<int> productionLine4 = new ActionBlock<int>(num => Console.WriteLine("Processed by line {0}: {1}", 4, num)); 
    ActionBlock<int> productionLine5 = new ActionBlock<int>(num => Console.WriteLine("Processed by line {0}: {1}", 5, num)); 

    productionQueue.LinkTo(productionLine1, x => x % 5 == 0); 
    productionQueue.LinkTo(productionLine2, x => x % 5 == 1); 
    productionQueue.LinkTo(productionLine3, x => x % 5 == 2); 
    productionQueue.LinkTo(productionLine4, x => x % 5 == 3); 
    productionQueue.LinkTo(productionLine5, x => x % 5 == 4); 

    return productionQueue; 
} 

mã này sẽ làm như mong đợi.

Ai đó có thể làm sáng tỏ lý do tạo động và liên kết các khối hành động không hoạt động?

P.S. Nếu tôi đột nhập vào mã ngay sau khi ITargetBlock<int> temp = BuildPipeline(5); tạm thời hiển thị 5 mục tiêu được liên kết với bộ đệm. Và Id của mỗi mục tiêu là khác nhau.

Cảm ơn trước

EDIT: Thêm những thay đổi được đề xuất bởi svick nhưng vẫn không tốt:

private static ITargetBlock<int> BuildPipeline(int NumProductionLines) 
{ 
    var productionQueue = new BufferBlock<int>(); 
    var opt = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 1 }; 

    for (int i = 0; i < NumProductionLines; i++) 
    { 
     ActionBlock<int> productionLine = new ActionBlock<int>(num => Console.WriteLine("Processed by line {0}: {1}", i + 1, num)); 

     int j = i; 
     productionQueue.LinkTo(productionLine, x => x % NumProductionLines == j); 
    } 

    ActionBlock<int> discardedLine = new ActionBlock<int>(num => Console.WriteLine("Discarded: {0}", num)); 
    productionQueue.LinkTo(discardedLine); 

    return productionQueue; 
} 

Bây giờ chỉ dữ liệu quá trình dây chuyền sản xuất thứ hai (một trong những thỏa mãn x% 5 == 1 vị ngữ). Và các dữ liệu không đáp ứng các vị ngữ, có nghĩa là tôi nhận được số tận cùng bằng 9 và 7.

EDIT: Mã Làm việc sẽ trông giống như sau:

private static ITargetBlock<int> BuildPipeline(int NumProductionLines) 
{ 
    var productionQueue = new BufferBlock<int>(); 
    var opt = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 1 }; 

    for (int i = 0; i < NumProductionLines; i++) 
    { 
     int j = i; 
     ActionBlock<int> productionLine = new ActionBlock<int>(num => Console.WriteLine("Processed by line {0}: {1}", j + 1, num)); 

     productionQueue.LinkTo(productionLine, x => x % NumProductionLines == j); 
    } 

    productionQueue.LinkTo(DataflowBlock.NullTarget<int>()); 

    return productionQueue; 
} 

Trả lời

5

Vấn đề là trong phiên bản đầu tiên của bạn, bạn đang sử dụng cùng một vị từ cho từng khối mục tiêu. Nói cách khác, vị từ không phụ thuộc vào i. Tuy nhiên, ngay cả khi nó đã làm, mã của bạn sẽ không hoạt động, vì biến số i được chia sẻ giữa các biến vị ngữ, vì vậy tất cả chúng sẽ sử dụng giá trị cuối cùng. Việc sửa chữa cho điều đó là để sao chép i vào một biến địa phương và sử dụng nó trong vị từ.

Mã này có thể trông như thế này:

private static ITargetBlock<int> BuildPipeline(int NumProductionLines) 
{ 
    var productionQueue = new BufferBlock<int>(); 

    for (int i = 0; i < NumProductionLines; i++) 
    { 
     int iCopy = i; 

     ActionBlock<int> productionLine = new ActionBlock<int>(
      num => Console.WriteLine("Processed by line {0}: {1}", iCopy + 1, num)); 

     productionQueue.LinkTo(
      productionLine, x => x % NumProductionLines == iCopy); 
    } 

    return productionQueue; 
} 

Nếu bạn đang thắc mắc tại sao không xử lý mã của bạn ít nhất là x % 5 == 1 số, đó là bởi vì các máy phát điện ngẫu nhiên có khả năng sẽ tạo ra một số mà không làm khớp với vị từ đó, vì vậy không có nào trong số ActionBlock s sẽ chấp nhận nó. Do đó, số sẽ nằm trong hàng đợi đầu ra của khối nguồn và các số khác sẽ không thể đi qua được.Nếu trong mã thực của bạn, tình huống tương tự có thể xảy ra và bạn muốn loại bỏ tất cả các số không phù hợp với bất kỳ biến vị ngữ nào, bạn có thể liên kết khối nguồn với số a block that does nothing và chấp nhận bất kỳ thứ gì sau khi bạn liên kết nó với tất cả các khối hữu ích của bạn:

productionQueue.LinkTo(DataflowBlock.NullTarget<int>()); 
+0

cảm ơn, sao chép i vào biến cục bộ đã giải quyết được. – Dimitri

+0

@Dimitri Như bạn có thể nhận thấy, bạn cần sử dụng bản sao trong khối lambda quá. Tôi đã sửa mã trong câu trả lời của mình. – svick

+0

Có, tôi đã thay thế mọi lần xuất hiện của tôi, cảm ơn bạn. Ngoài ra mã của tôi đã có lỗi trong vòng lặp for: thay vì vị ngữ hardcoded nó phụ thuộc vào biến. – Dimitri

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