Pengendalian acara tak segerak yang elegan dalam C#
Dalam aplikasi C#, jika kelas mengandungi acara (seperti acara 'GameShuttingDown') dan pengendali acara tidak segerak, mungkin terdapat masalah bahawa permainan ditutup sebelum pengendali acara menunggu selesai. Ini kerana acara itu sendiri adalah segerak, tetapi pengendalinya tidak segerak.
Walaupun boleh menggunakan mekanisme tak segerak untuk menggantikan acara, ini akan kehilangan kesederhanaan acara. Pendekatan yang lebih baik ialah mengekalkan ekspresi acara sambil mendayakan pemprosesan tak segerak. Kita boleh melakukan ini dengan menyesuaikan jenis perwakilan dan bukannya menggunakan standard EventHandler
.
Contoh berikut menunjukkan cara:
<code class="language-csharp">public class A { public event Func<object, EventArgs, Task> Shutdown; public async Task OnShutdown() { var handler = Shutdown; if (handler == null) { return; } var invocationList = handler.GetInvocationList(); var handlerTasks = invocationList.Select(h => ((Func<object, EventArgs, Task>)h)(this, EventArgs.Empty)).ToArray(); await Task.WhenAll(handlerTasks); } }</code>
Dalam kaedah OnShutdown()
, kami mula-mula mendapatkan salinan tempatan perwakilan acara. Kami kemudian memanggil semua pengendali dan menyimpan tugas yang dikembalikan dalam tatasusunan. Akhir sekali, kami menggunakan Task.WhenAll()
untuk menunggu semua tugasan selesai. Ini lebih ringkas daripada lelaran gelung.
Berikut ialah program konsol ringkas yang menunjukkan penggunaan:
<code class="language-csharp">public class Program { public static void Main(string[] args) { var a = new A(); a.Shutdown += Handler1; a.Shutdown += Handler2; a.Shutdown += Handler3; a.OnShutdown().Wait(); } public static async Task Handler1(object sender, EventArgs e) { Console.WriteLine("启动关闭处理程序 #1"); await Task.Delay(1000); Console.WriteLine("关闭处理程序 #1 完成"); } public static async Task Handler2(object sender, EventArgs e) { Console.WriteLine("启动关闭处理程序 #2"); await Task.Delay(5000); Console.WriteLine("关闭处理程序 #2 完成"); } public static async Task Handler3(object sender, EventArgs e) { Console.WriteLine("启动关闭处理程序 #3"); await Task.Delay(2000); Console.WriteLine("关闭处理程序 #3 完成"); } }</code>
Pendekatan ini mengekalkan kesederhanaan acara sambil memastikan pengendali melaksanakan secara tidak segerak, mengelakkan isu penyekatan segerak. Menggunakan kaedah Select
LINQ memudahkan kod, menjadikannya lebih mudah dibaca dan diselenggara.
Atas ialah kandungan terperinci Bagaimana untuk Menjadikan Acara C# Asynchronous?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!