0Pricing
C# Academy · บทเรียน

ผู้ผลิต/ผู้บริโภคด้วย Channels (ภาพรวม)

สร้างแบบจำลองคิวผู้ผลิต/ผู้บริโภคคล้าย Channels โดยใช้ BlockingCollection : บัฟเฟอร์แบบจำกัด (แรงดันย้อนกลับ) ผู้บริโภคหลายราย และการทำงานเสร็จสิ้นอย่างเรียบร้อย

ผู้ผลิต/ผู้บริโภคด้วย Channels (ภาพรวม) เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 3 บทเรียน

แนวคิดและเป้าหมาย

เป้าหมาย: สร้างกระบวนการส่งต่อระหว่างผู้ผลิตกับผู้บริโภคที่ปลอดภัย

  • แนวคิดของช่องทาง: คิวระหว่างผู้ผลิตกับผู้บริโภค
  • ความจุที่ มีขอบเขตช่วยสร้างแรงดันย้อนกลับ
  • รองรับ ผู้บริโภคหลายราย
  • ใช้ CompleteAdding เพื่อปิดการทำงานอย่างเรียบร้อย

ผู้ผลิตหนึ่งรายและผู้บริโภคหนึ่งราย

ลำดับการทำงานพื้นฐาน: ผู้ผลิตเรียก Add ผู้บริโภควนนำข้อมูลออกด้วย GetConsumingEnumerable จากนั้นเรียก CompleteAdding เพื่อจบการทำงาน

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
  public static void Main(string[] args)
  {
    // Unbounded by default; simple demo
    BlockingCollection<int> queue = new BlockingCollection<int>();

    // Producer
    Task producer = Task.Run(() =>
    {
      for (int i = 1; i <= 5; i++)
      {
        queue.Add(i);                 // enqueue
        Console.WriteLine("Produced " + i);
        Thread.Sleep(50);             // simulate work
      }
      queue.CompleteAdding();         // signal no more items
    });

    // Consumer
    Task consumer = Task.Run(() =>
    {
      foreach (int x in queue.GetConsumingEnumerable())
      {
        Console.WriteLine("Consumed " + x);
        Thread.Sleep(80);             // simulate processing
      }
      Console.WriteLine("Consumer done");
    });

    Task.WaitAll(producer, consumer);
  }
}

การสาธิตแรงดันย้อนกลับ

คิวที่ มีขอบเขตจะสร้างแรงดันย้อนกลับ: เมื่อคิวเต็ม Add จะบล็อกจนกว่าผู้บริโภคจะทำให้มีพื้นที่ว่าง

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
  public static void Main(string[] args)
  {
    // Bounded capacity introduces backpressure
    BlockingCollection<int> queue = new BlockingCollection<int>(boundedCapacity: 2);

    Task producer = Task.Run(() =>
    {
      for (int i = 1; i <= 5; i++)
      {
        queue.Add(i); // blocks when the buffer is full
        Console.WriteLine("Produced " + i + " (count=" + queue.Count + ")");
      }
      queue.CompleteAdding();
    });

    Task consumer = Task.Run(() =>
    {
      foreach (int x in queue.GetConsumingEnumerable())
      {
        Console.WriteLine("Consumed " + x);
        Thread.Sleep(120); // slower consumer -> producer will block sometimes
      }
    });

    Task.WaitAll(producer, consumer);
  }
}

ผู้บริโภคแบบกระจายงาน

ผู้บริโภคหลายราย แย่งรับรายการต่าง ๆ แบบกระจายงาน งานจะถูกแบ่งระหว่างเธรดโดยอัตโนมัติ

using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
  public static void Main(string[] args)
  {
    BlockingCollection<int> queue = new BlockingCollection<int>(3);

    Task prod = Task.Run(() =>
    {
      for (int i = 1; i <= 8; i++)
      {
        queue.Add(i);
        Console.WriteLine("Produced " + i);
        Thread.Sleep(30);
      }
      queue.CompleteAdding();
    });

    // Start 2 consumers that compete for items
    Task[] consumers = Enumerable.Range(1, 2).Select(id => Task.Run(() =>
    {
      foreach (int x in queue.GetConsumingEnumerable())
      {
        Console.WriteLine("C" + id + " got " + x);
        Thread.Sleep(100);
      }
      Console.WriteLine("C" + id + " done");
    })).ToArray();

    Task.WaitAll(consumers.Concat(new[] { prod }).ToArray());
  }
}

การจบการทำงานอย่างเรียบร้อย

ใช้ CompleteAdding และ GetConsumingEnumerable เพื่อจบการทำงานอย่างเรียบร้อยเมื่อคิวถูกใช้จนหมด

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
  static void Producer(BlockingCollection<string> q)
  {
    string[] lines = { "A", "B", "C", "D" };
    foreach (var s in lines)
    {
      q.Add(s);
      Console.WriteLine("Produced " + s);
    }
    q.CompleteAdding(); // signal completion
  }

  static void Consumer(BlockingCollection<string> q)
  {
    try
    {
      foreach (var item in q.GetConsumingEnumerable())
      {
        Console.WriteLine("Consumed " + item);
        Thread.Sleep(60);
      }
      Console.WriteLine("Consumer finished all items");
    }
    catch (InvalidOperationException)
    {
      // Thrown if taken after completion and empty; avoided by foreach above.
    }
  }

  public static void Main(string[] args)
  {
    var queue = new BlockingCollection<string>(2);
    Task p = Task.Run(() => Producer(queue));
    Task c = Task.Run(() => Consumer(queue));
    Task.WaitAll(p, c);
  }
}

เคล็ดลับและข้อควรระวัง

เคล็ดลับ:

  • เลือกใช้บัฟเฟอร์แบบ มีขอบเขต เพื่อป้องกันการใช้หน่วยความจำเพิ่มขึ้นเรื่อย ๆ
  • ใช้ GetConsumingEnumerable เพื่อหลีกเลี่ยงการแข่งขันกันขณะจบการทำงาน
  • ทำรายการงานให้มีขนาดเล็กและเป็นอิสระต่อกัน หลีกเลี่ยงสถานะที่ใช้ร่วมกัน
  • บันทึกและจัดการข้อผิดพลาดภายในผู้บริโภค เพื่อป้องกันการหยุดทำงานโดยไม่มีการแจ้งเตือน

จุดประสงค์ของ CompleteAdding

ตรวจสอบความเข้าใจอย่างรวดเร็ว: การเรียก CompleteAdding() บน BlockingCollection มีผลอย่างไร

ทบทวน

ทบทวน: ใช้ BlockingCollection แบบ มีขอบเขตเพื่อจำลองช่องทาง กระจายงานไปยัง ผู้บริโภคหลายราย และใช้ CompleteAdding เพื่อปิดการทำงานอย่างราบรื่น

คำถามที่พบบ่อย

บทเรียน “ผู้ผลิต/ผู้บริโภคด้วย Channels (ภาพรวม)” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ผู้ผลิต/ผู้บริโภคด้วย Channels (ภาพรวม)” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 3 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ผู้ผลิต/ผู้บริโภคด้วย Channels (ภาพรวม)”

สร้างแบบจำลองคิวผู้ผลิต/ผู้บริโภคคล้าย Channels โดยใช้ BlockingCollection : บัฟเฟอร์แบบจำกัด (แรงดันย้อนกลับ) ผู้บริโภคหลายราย และการทำงานเสร็จสิ้นอย่างเรียบร้อย คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน

บทเรียน “ผู้ผลิต/ผู้บริโภคด้วย Channels (ภาพรวม)” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม

ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. Parallel.ForEach และ PLINQ
  2. ผู้ผลิต/ผู้บริโภคด้วย Channels (ภาพรวม)
  3. การแลกเปลี่ยนระหว่างอัตราการประมวลผลกับเวลาแฝง
← กลับไปที่ C# Academy