แค่สงสัยว่าความแตกต่างระหว่างBeginInvoke()
และInvoke()
คืออะไร?
ส่วนใหญ่สิ่งที่แต่ละคนจะใช้สำหรับ
แก้ไข: อะไรคือความแตกต่างระหว่างการสร้างวัตถุเธรดและการเรียกใช้การเรียกนั้นและเพียงแค่เรียกBeginInvoke()
ผู้แทน? หรือพวกเขาเป็นสิ่งเดียวกัน
แค่สงสัยว่าความแตกต่างระหว่างBeginInvoke()
และInvoke()
คืออะไร?
ส่วนใหญ่สิ่งที่แต่ละคนจะใช้สำหรับ
แก้ไข: อะไรคือความแตกต่างระหว่างการสร้างวัตถุเธรดและการเรียกใช้การเรียกนั้นและเพียงแค่เรียกBeginInvoke()
ผู้แทน? หรือพวกเขาเป็นสิ่งเดียวกัน
คำตอบ:
คุณหมายถึงDelegate.Invoke
/ BeginInvoke
หรือControl.Invoke
/ BeginInvoke
?
Delegate.Invoke
: ดำเนินการแบบซิงโครนัสบนเธรดเดียวกันDelegate.BeginInvoke
: เรียกใช้แบบอะซิงโครนัสบนthreadpool
เธรดControl.Invoke
: ดำเนินการกับเธรด UI แต่การเรียกเธรดจะรอให้เสร็จสิ้นก่อนดำเนินการต่อControl.BeginInvoke
: ดำเนินการกับเธรด UI และการเรียกเธรดไม่รอให้เสร็จสมบูรณ์คำตอบของทิมกล่าวถึงเมื่อคุณอาจต้องการใช้BeginInvoke
ถึงแม้ว่ามันจะเหมาะสำหรับDelegate.BeginInvoke
ฉัน
สำหรับ Windows Forms แอพพลิเคผมจะแนะนำว่าคุณควรจะมักจะBeginInvoke
ใช้ ด้วยวิธีนี้คุณไม่ต้องกังวลเกี่ยวกับการหยุดชะงักตัวอย่างเช่น - แต่คุณต้องเข้าใจว่า UI อาจไม่ได้รับการอัปเดตเมื่อคุณดูครั้งต่อไป! โดยเฉพาะอย่างยิ่งคุณไม่ควรแก้ไขข้อมูลที่อาจใช้เธรด UI เพื่อจุดประสงค์ในการแสดงผล ตัวอย่างเช่นถ้าคุณมีPerson
ด้วยFirstName
และLastName
คุณสมบัติและคุณได้:
person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";
จากนั้น UI อาจจบลงด้วยการแสดง "Keyser Spacey" (มีโอกาสภายนอกที่สามารถแสดง "Kevin Soze" แต่ผ่านความแปลกประหลาดของโมเดลหน่วยความจำเท่านั้น)
อย่างไรก็ตามหากคุณไม่มีปัญหาประเภทนี้คุณสามารถทำให้Control.BeginInvoke
ถูกต้องได้ง่ายขึ้นและจะหลีกเลี่ยงเธรดพื้นหลังของคุณไม่ต้องรอโดยไม่มีเหตุผล หมายเหตุว่าทีมแบบฟอร์ม Windows ได้รับประกันได้ว่าคุณสามารถใช้Control.BeginInvoke
ใน "ไฟและลืม" ลักษณะ - EndInvoke
คือโดยที่ไม่เคยเรียกร้อง สิ่งนี้ไม่เป็นความจริงของการโทรแบบ async โดยทั่วไป: ปกติแล้ว BeginXXX ทุกคนควรมีการเรียก EndXXX ที่สอดคล้องกันโดยปกติแล้วในการโทรกลับ
จากคำตอบของ Jon Skeet มีหลายครั้งที่คุณต้องการเรียกผู้ร่วมประชุมและรอให้การดำเนินการเสร็จสิ้นก่อนที่เธรดปัจจุบันจะยังคงดำเนินต่อไป ในกรณีเหล่านั้นการเรียกใช้เรียกเป็นสิ่งที่คุณต้องการ
ในแอปพลิเคชันแบบมัลติเธรดคุณอาจไม่ต้องการให้เธรดรอให้ผู้รับมอบสิทธิ์ดำเนินการให้เสร็จสิ้นโดยเฉพาะหากผู้รับมอบสิทธิ์นั้นดำเนินการ I / O (ซึ่งอาจทำให้ผู้รับมอบสิทธิ์และบล็อกเธรดของคุณ)
ในกรณีเหล่านั้น BeginInvoke จะเป็นประโยชน์ โดยเรียกมันว่าคุณกำลังบอกผู้รับมอบสิทธิ์ที่จะเริ่มต้น แต่จากนั้นด้ายของคุณมีอิสระที่จะทำสิ่งอื่น ๆ ควบคู่ไปกับการมอบหมาย
การใช้ BeginInvoke จะเพิ่มความซับซ้อนของรหัสของคุณ แต่มีบางครั้งที่ประสิทธิภาพที่ปรับปรุงแล้วนั้นคุ้มค่ากับความซับซ้อน
ความแตกต่างระหว่างControl.Invoke()
และControl.BeginInvoke()
คือ
BeginInvoke()
จะกำหนดเวลาการดำเนินการแบบอะซิงโครนัสบนเธรด GUI เมื่อมีการกำหนดการกระทำแบบอะซิงโครนัสรหัสของคุณจะดำเนินต่อ ในเวลาต่อมา (คุณไม่รู้ว่าเมื่อใด) การกระทำแบบอะซิงโครนัสของคุณจะถูกดำเนินการInvoke()
จะดำเนินการการกระทำแบบอะซิงโครนัสของคุณ (บนเธรด GUI) และรอจนกว่าการกระทำของคุณจะเสร็จสิ้นข้อสรุปเชิงตรรกะคือผู้รับมอบสิทธิ์ที่คุณส่งไปInvoke()
สามารถมีค่าพารามิเตอร์หรือค่าส่งคืนในขณะที่ผู้รับมอบสิทธิ์ที่คุณส่งไปถึงBeginInvoke()
ไม่สามารถ (คุณต้องใช้ EndInvoke เพื่อดึงผลลัพธ์)
เพียงให้ตัวอย่างสั้น ๆ ในการทำงานเพื่อดูผลของความแตกต่าง
new Thread(foo).Start();
private void foo()
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart)delegate()
{
myTextBox.Text = "bing";
Thread.Sleep(TimeSpan.FromSeconds(3));
});
MessageBox.Show("done");
}
ถ้าใช้BeginInvoke , MessageBox จะปรากฏขึ้นพร้อมกันกับการอัพเดตข้อความ ถ้าใช้การเรียกใช้MessageBox จะปรากฏหลังจากผ่านไป 3 วินาที ดังนั้นการแสดงผลของการโทรแบบอะซิงโครนัส ( BeginInvoke ) และการโทรแบบซิงโครนัส ( เรียกใช้ )
Delegate.BeginInvoke () แบบอะซิงโครนัสเข้าคิวการโทรของผู้รับมอบสิทธิ์และส่งคืนการควบคุมทันที เมื่อใช้ Delegate.BeginInvoke () คุณควรโทร Delegate.EndInvoke () ในวิธีการโทรกลับเพื่อรับผลลัพธ์
Delegate.Invoke () เรียกผู้ได้รับมอบหมายในชุดข้อความเดียวกัน
เพียงเพิ่มสาเหตุและเวลาที่จะใช้ Invoke ()
ทั้ง Invoke () และ BeginInvoke () จะจัดการรหัสที่คุณระบุในเธรดโปรแกรมเลือกจ่ายงาน
แต่แตกต่างจาก BeginInvoke () Invoke () จะหยุดการทำงานเธรดของคุณจนกว่าโปรแกรมเลือกจ่ายงานจะเรียกใช้รหัสของคุณ คุณอาจต้องการใช้ Invoke () หากคุณต้องการหยุดการทำงานแบบอะซิงโครนัสชั่วคราวจนกว่าผู้ใช้จะได้รับข้อเสนอแนะบางอย่าง
ตัวอย่างเช่นคุณสามารถเรียกใช้ Invoke () เพื่อเรียกใช้โค้ดขนาดสั้นที่แสดงกล่องโต้ตอบตกลง / ยกเลิก หลังจากที่ผู้ใช้คลิกปุ่มและรหัส marshaled ของคุณเสร็จสมบูรณ์วิธีการเรียกใช้ () จะกลับมาและคุณสามารถดำเนินการตามการตอบสนองของผู้ใช้
ดู Pro WPF ใน C # ตอนที่ 31