Jika saya menyiapkan beberapa penangan acara, seperti ini:
_webservice.RetrieveDataCompleted += ProcessData1;
_webservice.RetrieveDataCompleted += ProcessData2;
urutan apa yang dijalankan penangan saat acara RetrieveDataCompleted
dipecat? Apakah mereka berjalan di utas yang sama dan berurutan dalam urutan yang terdaftar?
c#
asynchronous
event-handling
Phillip Ngan
sumber
sumber
Jawaban:
Saat ini, mereka dieksekusi sesuai urutan mereka terdaftar. Namun, ini adalah detail implementasi, dan saya tidak akan mengandalkan perilaku ini tetap sama di versi mendatang, karena tidak diwajibkan oleh spesifikasi.
sumber
Dari sini: Kelas Delegasi
sumber
add
danremove
sebuah acara belum tentu diimplementasikan sebagai delegasi multi-pemain.Anda dapat mengubah urutan dengan melepaskan semua penangan, lalu memasang kembali dalam urutan yang diinginkan.
public event EventHandler event1; public void ChangeHandlersOrdering() { if (event1 != null) { List<EventHandler> invocationList = event1.GetInvocationList() .OfType<EventHandler>() .ToList(); foreach (var handler in invocationList) { event1 -= handler; } //Change ordering now, for example in reverese order as follows for (int i = invocationList.Count - 1; i >= 0; i--) { event1 += invocationList[i]; } } }
sumber
Urutannya sewenang-wenang. Anda tidak dapat mengandalkan penangan yang dieksekusi dalam urutan tertentu dari satu pemanggilan ke pemanggilan berikutnya.
Sunting: Dan juga - kecuali ini hanya karena ingin tahu - fakta yang perlu Anda ketahui merupakan indikasi masalah desain yang serius .
sumber
Mereka dijalankan sesuai urutan pendaftarannya.
RetrieveDataCompleted
adalah Delegasi Multicast . Saya melihat melalui reflektor untuk mencoba dan memverifikasi, dan sepertinya array digunakan di belakang layar untuk melacak semuanya.sumber
Jika seseorang perlu melakukan ini dalam konteks System.Windows.Forms.Form, berikut adalah contoh membalik urutan acara Tampil.
using System; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Windows.Forms; namespace ConsoleApplication { class Program { static void Main() { Form form; form = createForm(); form.ShowDialog(); form = createForm(); invertShownOrder(form); form.ShowDialog(); } static Form createForm() { var form = new Form(); form.Shown += (sender, args) => { Console.WriteLine("form_Shown1"); }; form.Shown += (sender, args) => { Console.WriteLine("form_Shown2"); }; return form; } static void invertShownOrder(Form form) { var events = typeof(Form) .GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic) .GetValue(form, null) as EventHandlerList; var shownEventKey = typeof(Form) .GetField("EVENT_SHOWN", BindingFlags.NonPublic | BindingFlags.Static) .GetValue(form); var shownEventHandler = events[shownEventKey] as EventHandler; if (shownEventHandler != null) { var invocationList = shownEventHandler .GetInvocationList() .OfType<EventHandler>() .ToList(); foreach (var handler in invocationList) { events.RemoveHandler(shownEventKey, handler); } for (int i = invocationList.Count - 1; i >= 0; i--) { events.AddHandler(shownEventKey, invocationList[i]); } } } } }
sumber
MulticastDelegate memiliki daftar delegasi yang ditautkan, yang disebut daftar permintaan, yang terdiri dari satu atau lebih elemen. Saat delegasi multicast dipanggil, delegasi dalam daftar pemanggilan dipanggil secara sinkron dalam urutan kemunculannya. Jika kesalahan terjadi selama eksekusi daftar maka pengecualian dilemparkan.
sumber
Tetapi tidak ada yang mengatakan bahwa daftar pemanggilan mempertahankan delegasi dalam urutan yang sama saat mereka ditambahkan. Dengan demikian, urutan permintaan tidak dijamin.
sumber
Ini adalah fungsi yang akan menempatkan fungsi penanganan kejadian baru di mana pun Anda inginkan dalam daftar pemanggilan multidelegate.
private void addDelegateAt(ref YourDelegate initial, YourDelegate newHandler, int position) { Delegate[] subscribers = initial.GetInvocationList(); Delegate[] newSubscriptions = new Delegate[subscribers.Length + 1]; for (int i = 0; i < newSubscriptions.Length; i++) { if (i < position) newSubscriptions[i] = subscribers[i]; else if (i==position) newSubscriptions[i] = (YourDelegate)newHandler; else if (i > position) newSubscriptions[i] = subscribers[i-1]; } initial = (YourDelegate)Delegate.Combine(newSubscriptions); }
Kemudian Anda selalu dapat menghapus fungsi dengan '- =' di mana pun dalam kode Anda.
PS - Saya tidak melakukan penanganan kesalahan untuk parameter 'posisi'.
sumber
Saya punya masalah serupa. Dalam kasus saya, itu diperbaiki dengan sangat mudah. Saya belum pernah melihat delegasi yang tidak menggunakan operator + =. Masalah saya diperbaiki dengan memiliki satu delegasi yang selalu ditambahkan di akhir, yang lainnya selalu ditambahkan di awal. Contoh OP akan menjadi seperti ini:
Dalam kasus pertama, ProcessData1 akan dipanggil terakhir. Dalam kasus kedua, ProcessData2 akan dipanggil terlebih dahulu.
sumber