Jawaban atas pertanyaan ini terletak pada cara kerja Kontrol C #
Kontrol dalam Formulir Windows terikat ke utas tertentu dan tidak aman utas. Oleh karena itu, jika Anda memanggil metode kontrol dari utas yang berbeda, Anda harus menggunakan salah satu metode pemanggilan kontrol untuk mengatur panggilan ke utas yang tepat. Properti ini bisa digunakan untuk menentukan apakah Anda harus memanggil metode pemanggilan, yang bisa berguna jika Anda tidak tahu thread apa yang memiliki kontrol.
Dari Control.InvokeRequired
Secara efektif, apa yang dilakukan Invoke adalah memastikan bahwa kode yang Anda panggil terjadi pada thread yang kontrolnya "aktif" secara efektif mencegah pengecualian lintas thread.
Dari perspektif historis, di .Net 1.1, ini sebenarnya diizinkan. Maksudnya adalah Anda dapat mencoba dan mengeksekusi kode pada utas "GUI" dari utas latar belakang mana pun dan ini sebagian besar akan berfungsi. Terkadang itu hanya akan menyebabkan aplikasi Anda keluar karena Anda secara efektif mengganggu utas GUI ketika sedang melakukan sesuatu yang lain. Ini adalah Pengecualian Berulir Lintas - bayangkan mencoba memperbarui TextBox saat GUI melukis sesuatu yang lain.
- Tindakan mana yang diprioritaskan?
- Apakah mungkin keduanya terjadi sekaligus?
- Apa yang terjadi pada semua perintah lain yang perlu dijalankan GUI?
Secara efektif, Anda mengganggu antrean, yang dapat menimbulkan banyak konsekuensi tak terduga. Memanggil secara efektif adalah cara "sopan" untuk memasukkan apa yang ingin Anda lakukan ke dalam antrean tersebut, dan aturan ini diberlakukan dari .Net 2.0 dan seterusnya melalui InvalidOperationException yang dilempar .
Untuk memahami apa yang sebenarnya terjadi di balik layar, dan apa yang dimaksud dengan "GUI Thread", ada gunanya untuk memahami apa itu Message Pump atau Message Loop.
Ini sebenarnya sudah dijawab dalam pertanyaan " Apa itu Pompa Pesan " dan bacaan yang direkomendasikan untuk memahami mekanisme aktual yang Anda gunakan saat berinteraksi dengan kontrol.
Bacaan lain yang mungkin berguna bagi Anda termasuk:
Ada apa dengan Begin Invoke
Salah satu aturan utama pemrograman Windows GUI adalah bahwa hanya utas yang membuat kontrol yang dapat mengakses dan / atau mengubah isinya (kecuali untuk beberapa pengecualian yang terdokumentasi). Coba lakukan dari utas lain mana pun dan Anda akan mendapatkan perilaku tak terduga mulai dari kebuntuan, hingga pengecualian hingga UI yang setengah diperbarui. Cara yang benar kemudian untuk memperbarui kontrol dari utas lain adalah dengan memposting pesan yang sesuai ke antrian pesan aplikasi. Ketika message pump menjalankan pesan itu, kontrol akan diperbarui, pada thread yang sama yang membuatnya (ingat, pompa pesan berjalan pada thread utama).
dan, untuk ikhtisar kode yang lebih banyak dengan sampel yang representatif:
Operasi Lintas Benang Tidak Valid
public delegate void ControlStringConsumer(Control control, string text);
public void SetText(Control control, string text) {
if (control.InvokeRequired) {
control.Invoke(new ControlStringConsumer(SetText), new object[]{control, text});
} else {
control.Text=text;
}
}
Setelah Anda menghargai InvokeRequired, Anda mungkin ingin mempertimbangkan menggunakan metode ekstensi untuk menggabungkan panggilan ini. Ini dengan cakap tercakup dalam pertanyaan Stack Overflow Membersihkan Kode yang Dikotori dengan Permintaan Diperlukan .
Ada juga tulisan lebih lanjut tentang apa yang terjadi secara historis yang mungkin menarik.