เมื่อทำงานกับข้อมูลในสภาพแวดล้อมที่มีหลายเธรด (Multithreaded Environment) สิ่งที่ต้องคำนึงถึงมากที่สุดคือการจัดการข้อมูลอย่างปลอดภัยและมีประสิทธิภาพ .NET Framework มีคอลเลกชันชนิดพิเศษหลายชนิดที่ถูกออกแบบมาเพื่อจัดการกับสถานการณ์ดังกล่าว หนึ่งในคอลเลกชันที่สำคัญคือ ConcurrentQueue<T>
และ ConcurrentStack<T>
ConcurrentQueue
ConcurrentQueue<T>
เป็นคอลเลกชันที่ใช้สำหรับเก็บข้อมูลแบบ First-In, First-Out (FIFO) ซึ่งหมายความว่าข้อมูลที่ถูกเพิ่มเข้ามาก่อนจะถูกดึงออกก่อน เหมาะสมอย่างยิ่งสำหรับการจัดการข้อมูลในลักษณะที่ต้องการให้เรียงลำดับตามลำดับการเพิ่มข้อมูล เช่น การจัดการคิวของงานที่ต้องดำเนินการในเธรดหลายๆ เธรดพร้อมกัน
เมธอดที่สำคัญของ ConcurrentQueue:
- Enqueue(T): ใช้สำหรับเพิ่มข้อมูลเข้าไปในคิว
- TryPeek(out T): ใช้เพื่อดึงข้อมูลที่อยู่ข้างหน้าสุดของคิวออกมาโดยไม่ลบออกจากคิว
- TryDequeue(out T): ใช้เพื่อดึงข้อมูลที่อยู่ข้างหน้าสุดของคิวออกมาและลบออกจากคิว
- Count: ใช้เพื่อนับจำนวนข้อมูลที่อยู่ในคิว
- IsEmpty: ใช้เพื่อตรวจสอบว่าคิวว่างหรือไม่
ตัวอย่างการใช้ ConcurrentQueue:
ConcurrentQueue<int> queue = new ConcurrentQueue<int>();
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
if (queue.TryDequeue(out int result))
{
Console.WriteLine($"Dequeued: {result}");
}
ConcurrentStack
ConcurrentStack<T>
คล้ายคลึงกับ ConcurrentQueue<T>
แต่การทำงานจะเป็นแบบ Last-In, First-Out (LIFO) หรือ Stack ซึ่งหมายความว่าข้อมูลที่ถูกเพิ่มเข้ามาล่าสุดจะถูกดึงออกมาก่อน
เมธอดที่สำคัญของ ConcurrentStack:
- Push(T): ใช้สำหรับเพิ่มข้อมูลเข้าไปในสแต็ก
- TryPop(out T): ใช้เพื่อดึงข้อมูลที่อยู่บนสุดของสแต็กออกมาและลบออกจากสแต็ก
- Count: ใช้เพื่อนับจำนวนข้อมูลที่อยู่ในสแต็ก
- IsEmpty: ใช้เพื่อตรวจสอบว่าสแต็กว่างหรือไม่
ตัวอย่างการใช้ ConcurrentStack:
ConcurrentStack<int> stack = new ConcurrentStack<int>();
stack.Push(1);
stack.Push(2);
stack.Push(3);
if (stack.TryPop(out int result))
{
Console.WriteLine($"Popped: {result}");
}
ทั้ง ConcurrentQueue<T>
และ ConcurrentStack<T>
เป็นเครื่องมือที่มีประโยชน์มากในการจัดการข้อมูลในสถานการณ์ที่มีการทำงานแบบขนาน เพราะสามารถช่วยให้การจัดการข้อมูลมีความปลอดภัยจากปัญหาการแข่งขัน (Race Condition) ที่มักเกิดขึ้นในโปรแกรมที่ใช้หลายเธรด
ในการเลือกใช้คอลเลกชันที่เหมาะสม ขึ้นอยู่กับลักษณะการจัดการข้อมูลที่ต้องการ เช่น หากต้องการรักษาลำดับการทำงานของข้อมูล ConcurrentQueue<T>
จะเป็นตัวเลือกที่ดี แต่หากต้องการให้ข้อมูลที่เพิ่มเข้ามาล่าสุดถูกดึงออกก่อน ConcurrentStack<T>
จะเหมาะสมกว่า