ผู้ผลิต/ผู้บริโภคด้วย 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
ทบทวน
ทบทวน: ใช้ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- Parallel.ForEach และ PLINQ
- ผู้ผลิต/ผู้บริโภคด้วย Channels (ภาพรวม)
- การแลกเปลี่ยนระหว่างอัตราการประมวลผลกับเวลาแฝง