在 C# 中,事件的发布和订阅机制遵循以下规则:
1. 默认行为:同步执行,阻塞发布线程
如果事件订阅者(主线程)的处理方法是同步的,子线程在发布事件后会等待所有订阅者执行完毕,才会继续执行后续代码。
Block_Test.cs
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace WindowsFormsApp1
{
public class Block_Test
{
// 定义一个委托类型
public delegate void MyEventHandler(object sender, EventArgs e);
// 定义一个事件
public event MyEventHandler MyEvent;
// 触发事件的方法
public void TriggerEvent()
{
Console.WriteLine($"thread--{Thread.CurrentThread.ManagedThreadId}--");
Console.WriteLine("事件触发前");
// 触发事件,会调用所有注册的处理程序
MyEvent?.Invoke(this, EventArgs.Empty);
Console.WriteLine("事件触发后");
}
}
}
program.cs
cs
public Form1()
{
InitializeComponent();
Console.WriteLine($"Form1--{Thread.CurrentThread.ManagedThreadId}--");
signalThread = new Thread(publisher.TriggerEvent);
signalThread.IsBackground = true; // 设置为后台线程
//OnEventHandlerAsync();//异步订阅(不阻塞发布线程)
// 注册事件处理程序
publisher.MyEvent += Program_MyEvent;//阻塞发布线程
// 触发事件
//program.TriggerEvent();
}
public void Program_MyEvent(object sender, EventArgs e)
{
//下面的代码发布线程会阻塞
if (this.InvokeRequired) // 判断是否需要切换线程
{
// 需要切换到主线程
this.Invoke(new EventHandler(Program_MyEvent), sender, e);
return;
}
Console.WriteLine($"mian--{Thread.CurrentThread.ManagedThreadId}--");
Console.WriteLine("事件处理程序执行中");
// 模拟一些工作
System.Threading.Thread.Sleep(10000);
this.button1.Text = "button2";
Console.WriteLine("事件处理程序执行完毕");
}
2. 异步执行:发布后立即继续(不阻塞)
如果需要子线程在发布事件后立即继续执行,可以在订阅时使用异步处理:
cs
public Form1()
{
InitializeComponent();
Console.WriteLine($"Form1--{Thread.CurrentThread.ManagedThreadId}--");
signalThread = new Thread(publisher.TriggerEvent);
signalThread.IsBackground = true; // 设置为后台线程
OnEventHandlerAsync();//异步订阅(不阻塞发布线程)
// 注册事件处理程序
//publisher.MyEvent += Program_MyEvent;//阻塞发布线程
// 触发事件
//program.TriggerEvent();
}
private void OnEventHandlerAsync()
{
// 异步订阅(不阻塞发布线程)
publisher.MyEvent += async (sender, e) =>
{
await Task.Run(() =>
{
Console.WriteLine("主线程:异步处理事件(模拟耗时操作)");
Thread.Sleep(10000);
Console.WriteLine("主线程:异步事件处理完成");
});
};
}