从 Component 到 BackgroundWorker
在 .NET Framework 2.0 时代,微软引入了 BackgroundWorker 来解决 WinForm/WPF 场景下“耗时操作阻塞 UI 线程”的问题;而 Component 早在 1.0 就已存在,是所有可视化/非可视化设计器的“基类”。理解这两者的源码与机制,可以帮助我们:
更精确地调试遗留代码;
在需要设计时支持时(如自定义控件/组件)少走弯路;
在无法使用 async-await 的老项目中做最小侵入式改造。
2️⃣ Component 类:所有“组件”的鼻祖
2.1 命名空间与程序集
// 所在程序集:System.ComponentModel.Primitives.dll
namespace System.ComponentModel
2.2 继承链与接口实现
System.Object
└─ System.MarshalByRefObject // 支持跨 AppDomain 远程调用
└─ System.ComponentModel.Component
├─ 实现 IComponent // 提供 Site 与 Disposed 事件
└─ 实现 IDisposable // 标准 Dispose 模式
2.3 设计时元数据
[ComVisible(true)]:可被 COM 调用。
[ClassInterface(ClassInterfaceType.AutoDispatch)]:为 COM 客户端生成双重接口。
[DesignerCategory(“Component”)]:告诉 Visual Studio 使用 ComponentDesigner。
2.4 核心字段与线程安全
private static readonly object EventDisposed = new object();
private ISite site;
private EventHandlerList events; // 延迟创建,减少内存
- 所有事件都通过
EventHandlerList
存储,避免每个事件一个字段,节省内存。 - 对
events
的访问采用“延迟初始化 + 双检锁”。
2.5 事件系统:EventHandlerList 的魔法
public event EventHandler Disposed
{
add { Events.AddHandler(EventDisposed, value); }
remove { Events.RemoveHandler(EventDisposed, value); }
}
- 通过
object
类型的 key(而非字符串)避免冲突。 EventHandlerList
内部使用单向链表,添加/删除 O(1)。
2.6 Dispose 模式深度解析
~Component() { Dispose(false); }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposing) return;
lock (this)
{
if (site?.Container != null)
site.Container.Remove(this); // 设计器撤销时自动清理
((EventHandler)events?[EventDisposed])?.Invoke(this, EventArgs.Empty);
}
}
标准 Dispose 模式 + lock(this) 保证线程安全。
在 VS 设计器中,当用户从设计面板上删除组件时,Container.Remove 会触发 Dispose。
2.7 设计时支持:Site / Container / DesignMode
ISite:为组件提供“宿主”信息(名称、容器、设计模式标志、全局服务)。
IContainer:管理一组组件的生命周期。
DesignMode:运行时永远返回 false,仅在设计器进程返回 true。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
7. 本站有不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别!
66源码网 » 从 Component 到 BackgroundWorker