翻译《The Old New Thing》- What does the CS_CLASSDC class style do?

What does the CS_CLASSDC class style do? - The Old New Thing (microsoft.com)icon-default.png?t=N7T8https://devblogs.microsoft.com/oldnewthing/20060602-00/?p=30993

Raymond Chen 2006年06月02日


CS_CLASSDC 类样式有什么作用?

简要

        本文讨论了CS_CLASSDC类样式的问题,指出它会导致跨窗口和线程间共享同一个设备上下文(DC),从而引发竞态条件和难以调试的错误。作者建议现代软件不应使用此样式,它仅适用于16位Windows的单线程环境。

正文

       上一次,我讨论了CS_OWNDC类样式的历史背景,以及为什么它一开始听起来是个好主意,但当你再想想时,却变成了一个可怕的想法。 CS_CLASSDC类样式也是一样的,但更糟糕,因为它继承了CS_OWNDC的所有问题,并将它们放大了。回想一下,CS_OWNDC类样式指示窗口管理器为窗口创建一个DC(设备上下文),并使用这个单一的DC响应BeginPaintGetDC的调用。

  CS_CLASSDC进一步发展了这一点,并为该类的所有窗口创建了一个DC。所以,上一次我展示的那个函数认为它对一个窗口有两个不同的DC的问题,现在甚至可能发生在不同窗口之间。 你以为你有一个窗口有一个DC,另一个窗口有另一个DC,但实际上它们是同一个! 更糟糕的是,两个线程可以同时使用同一个DC。GDI(图形设备接口)中没有任何东西禁止这样做;

        这只是一场看哪个线程的更改占上风的比赛:“最后写入者获胜”。 想象一下,两个线程恰好各自有一个来自同一个窗口类的CS_CLASSDC窗口,假设两个窗口都需要重绘。每个窗口都会收到一个WM_PAINT消息,两个线程都进入它们的绘制代码。但是这些线程不知道的是,它们正在操作同一个DC

线程A线程B
HDC hdc = BeginPaint(hwnd, &ps);
HDC hdc = BeginPaint(hwnd, &ps);
SetTextColor(hdc, red);
SetTextColor(hdc, blue);
DrawText(hdc, …);
DrawText(hdc, …);

        线程A期望文本是红色的,它将文本颜色设置为红色,然后绘制文本。它怎么会想到就在那一刻,线程B去把它改成了蓝色?

        这是你很可能永远无法在受控条件下研究的竞态条件错误类型。你只会收到客户的bug报告,说可能每个月一次,一个项目以错误的色调出现,你可能偶尔会自己看到它,但当你设置调试器断点时,它永远不会发生。即使你添加了额外的诊断代码,你所看到的只是这个:

...
SetTextColor(hdc, red);
ASSERT(GetTextColor(hdc) == red); // 断言触发了!
DrawText(hdc, ...);

        很好,断言触发了。 你刚刚设置的颜色不在那里。 现在你打算怎么办? 也许你只会说“愚蠢的有缺陷的Windows”,然后改变你的代码为

// 愚蠢的有缺陷的Windows。出于某种原因,
// 大约每个月一次,SetTextColor不起作用
// 我们必须调用它两次。
do {
    SetTextColor(hdc, red);
} while (GetTextColor(hdc) != red);
DrawText(hdc, ...);

        甚至这也不能解决问题,因为线程B可能在GetTextColorDrawText调用之后将颜色改为蓝色。 现在,每六个月只有一次项目以错误的色调出现。

        你咒骂微软,发誓从现在开始开发Mac软件。

        好吧,所以现在我希望我说服了你,CS_CLASSDC是一个可怕的想法。 但如果它如此根本上存在缺陷,为什么它最初会存在呢?

        因为16位Windows是合作式多任务的。 在16位世界中,你不必担心另一个线程潜入并搞乱你的DC,因为,正如我已经指出的,你正在运行意味着没有其他人正在运行。这种多线程灾难场景根本不可能发生,所以CS_CLASSDC只是比CS_OWNDC稍微不那么疯狂一点。 引入具有单个进程中多个线程的抢占式多任务处理,是将我们带入了“这根本没有机会正常工作”的世界。 这个类样式的存在是为了那些在16位代码中使用它的人可以移植到Win32(只要他们承诺保持单线程应用程序),但没有任何现代软件应该使用它。

  • 13
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0x0007

可不可奖励我吃只毛嘴鸡 馋😋

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值