พิจารณาวิธีการสมมุติของวัตถุที่ทำสิ่งต่างๆให้คุณ:
public class DoesStuff
{
BackgroundWorker _worker = new BackgroundWorker();
...
public void CancelDoingStuff()
{
_worker.CancelAsync();
//todo: Figure out a way to wait for BackgroundWorker to be cancelled.
}
}
จะรอให้ BackgroundWorker ทำได้อย่างไร?
ในอดีตผู้คนได้พยายาม:
while (_worker.IsBusy)
{
Sleep(100);
}
แต่การหยุดชะงักนี้เนื่องจากIsBusy
ไม่ได้รับการล้างจนกว่าRunWorkerCompleted
จะมีการจัดการเหตุการณ์และเหตุการณ์นั้นจะไม่สามารถจัดการได้จนกว่าแอปพลิเคชันจะไม่ได้ใช้งาน แอปพลิเคชันจะไม่ทำงานจนกว่าผู้ปฏิบัติงานจะเสร็จสิ้น (นอกจากนี้ยังเป็นห่วงที่วุ่นวาย - น่าขยะแขยง)
คนอื่น ๆ ได้เพิ่มการแยกที่แนะนำไว้ใน:
while (_worker.IsBusy)
{
Application.DoEvents();
}
ปัญหาที่เกิดขึ้นคือApplication.DoEvents()
ทำให้ข้อความที่อยู่ในคิวถูกประมวลผลซึ่งทำให้เกิดปัญหา re-entrancy (.NET ไม่ใช่ re-entrant)
ฉันหวังว่าจะใช้วิธีแก้ปัญหาบางอย่างที่เกี่ยวข้องกับอ็อบเจ็กต์การซิงโครไนซ์เหตุการณ์โดยที่โค้ดรอเหตุการณ์ที่ผู้จัดการRunWorkerCompleted
เหตุการณ์ของผู้ปฏิบัติงานกำหนดไว้ สิ่งที่ต้องการ:
Event _workerDoneEvent = new WaitHandle();
public void CancelDoingStuff()
{
_worker.CancelAsync();
_workerDoneEvent.WaitOne();
}
private void RunWorkerCompletedEventHandler(sender object, RunWorkerCompletedEventArgs e)
{
_workerDoneEvent.SetEvent();
}
แต่ฉันกลับไปสู่ภาวะชะงักงัน: ตัวจัดการเหตุการณ์ไม่สามารถทำงานได้จนกว่าแอปพลิเคชันจะไม่ได้ใช้งานและแอปพลิเคชันจะไม่ทำงานเนื่องจากกำลังรอเหตุการณ์
แล้วคุณจะรอให้ BackgroundWorker เสร็จสิ้นได้อย่างไร?
อัปเดต ผู้คนดูเหมือนจะสับสนกับคำถามนี้ ดูเหมือนพวกเขาจะคิดว่าฉันจะใช้ BackgroundWorker เป็น:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += MyWork;
worker.RunWorkerAsync();
WaitForWorkerToFinish(worker);
นั่นคือไม่ได้ก็คือว่าไม่ได้สิ่งที่ฉันทำและนั่นคือไม่ได้สิ่งที่จะถูกถามนี่ หากเป็นเช่นนั้นจะไม่มีประโยชน์ในการใช้คนทำงานเบื้องหลัง