Adakah yang bisa menjelaskan pernyataan yang tertulis di tautan ini
Invoke(Delegate):
Menjalankan delegasi yang ditentukan pada utas yang memiliki pegangan jendela yang mendasari kontrol.
Adakah yang bisa menjelaskan apa artinya (terutama yang berani) saya tidak bisa mendapatkannya dengan jelas
Jawaban:
Jawaban atas pertanyaan ini terletak pada cara kerja Kontrol C #
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.
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
dan, untuk ikhtisar kode yang lebih banyak dengan sampel yang representatif:
Operasi Lintas Benang Tidak Valid
// the canonical form (C# consumer) public delegate void ControlStringConsumer(Control control, string text); // defines a delegate type public void SetText(Control control, string text) { if (control.InvokeRequired) { control.Invoke(new ControlStringConsumer(SetText), new object[]{control, text}); // invoking itself } else { control.Text=text; // the "functional part", executing only on the main thread } }
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.
sumber
Sebuah objek kontrol atau jendela di Windows Forms hanyalah pembungkus di sekitar jendela Win32 yang diidentifikasi oleh pegangan (kadang-kadang disebut HWND). Kebanyakan hal yang Anda lakukan dengan kontrol pada akhirnya akan menghasilkan panggilan API Win32 yang menggunakan pegangan ini. Pegangan dimiliki oleh utas yang membuatnya (biasanya utas utama), dan tidak boleh dimanipulasi oleh utas lain. Jika karena alasan tertentu Anda perlu melakukan sesuatu dengan kontrol dari utas lain, Anda dapat menggunakan
Invoke
utas utama untuk melakukannya atas nama Anda.Misalnya, jika Anda ingin mengubah teks label dari utas pekerja, Anda dapat melakukan sesuatu seperti ini:
theLabel.Invoke(new Action(() => theLabel.Text = "hello world from worker thread!"));
sumber
this.Invoke(() => this.Enabled = true);
Apa pun yangthis
dimaksud pasti ada di utas saat ini, bukan?Jika Anda ingin mengubah kontrol, itu harus dilakukan di thread tempat kontrol dibuat.
Invoke
Metode ini memungkinkan Anda untuk mengeksekusi metode di thread terkait (thread yang memiliki pegangan jendela yang mendasari kontrol).Di bawah contoh thread1 melontarkan pengecualian karena SetText1 mencoba mengubah textBox1.Text dari utas lain. Namun di thread2, Tindakan di SetText2 dijalankan di thread tempat TextBox dibuat
private void btn_Click(object sender, EvenetArgs e) { var thread1 = new Thread(SetText1); var thread2 = new Thread(SetText2); thread1.Start(); thread2.Start(); } private void SetText1() { textBox1.Text = "Test"; } private void SetText2() { textBox1.Invoke(new Action(() => textBox1.Text = "Test")); }
sumber
Invoke((MethodInvoker)delegate{ textBox1.Text = "Test"; });
sumber
Dalam istilah praktis, ini berarti delegasi dijamin akan dipanggil di thread utama. Ini penting karena dalam kasus kontrol windows jika Anda tidak memperbarui propertinya pada utas utama, maka Anda tidak akan melihat perubahannya, atau kontrol tersebut memunculkan pengecualian.
Polanya adalah:
void OnEvent(object sender, EventArgs e) { if (this.InvokeRequired) { this.Invoke(() => this.OnEvent(sender, e); return; } // do stuff (now you know you are on the main thread) }
sumber
this.Invoke(delegate)
pastikan bahwa Anda memanggil delegasi argumen kethis.Invoke()
pada utas utama / utas yang dibuat.Saya dapat mengatakan aturan Thumb tidak mengakses kontrol formulir Anda kecuali dari utas utama.
Mungkin baris berikut masuk akal untuk menggunakan Invoke ()
private void SetText(string text) { // InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. if (this.textBox1.InvokeRequired) { SetTextCallback d = new SetTextCallback(SetText); this.Invoke(d, new object[] { text }); } else { this.textBox1.Text = text; } }
Ada beberapa situasi meskipun Anda membuat utas Threadpool (yaitu utas pekerja) itu akan berjalan di utas utama. Ini tidak akan membuat utas baru karena utas utama tersedia untuk memproses instruksi lebih lanjut. Jadi Pertama selidiki apakah utas yang sedang berjalan adalah utas utama menggunakan
this.InvokeRequired
if return true, kode saat ini berjalan pada utas pekerja jadi panggil this.Invoke (d, new object [] {text});else secara langsung memperbarui kontrol UI (Di sini Anda dijamin bahwa Anda menjalankan kode di utas utama.)
sumber
Artinya, delegasi akan berjalan di UI thread, meskipun Anda memanggil metode tersebut dari pekerja latar belakang atau thread pool thread. Elemen UI memiliki afinitas utas - mereka hanya suka berbicara langsung ke satu utas: utas UI. Utas UI didefinisikan sebagai utas yang membuat contoh kontrol, dan oleh karena itu dikaitkan dengan pegangan jendela. Tapi semua itu adalah detail implementasi.
Poin utamanya adalah: Anda akan memanggil metode ini dari thread pekerja sehingga Anda dapat mengakses UI (untuk mengubah nilai di label, dll) - karena Anda tidak diizinkan melakukannya dari thread lain selain thread UI.
sumber
Delegasi pada dasarnya adalah inline
Action
atauFunc<T>
. Anda bisa mendeklarasikan delegasi di luar lingkup metode yang Anda jalankan atau menggunakanlambda
ekspresi (=>
); karena Anda menjalankan delegasi dalam sebuah metode, Anda menjalankannya pada utas yang sedang dijalankan untuk jendela / aplikasi saat ini yang sedikit dicetak tebal.Contoh Lambda
int AddFiveToNumber(int number) { var d = (int i => i + 5); d.Invoke(number); }
sumber
Artinya, delegasi yang Anda teruskan dieksekusi di thread yang membuat objek Control (yaitu UI thread).
Anda perlu memanggil metode ini ketika aplikasi Anda multi-threaded dan Anda ingin melakukan beberapa operasi UI dari thread selain UI thread, karena jika Anda hanya mencoba memanggil metode pada Kontrol dari thread berbeda, Anda akan mendapatkan System.InvalidOperationException.
sumber