为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 Task.Delay 会破坏线程的 STA 状态?

为什么 Task.Delay 会破坏线程的 STA 状态?

C#
心有法竹 2022-12-24 09:44:16
介绍这是一个很长的问题!您会在开始时找到有关该问题的一些背景知识,然后是代码示例,这些示例已针对表示形式进行了简化,然后是问题。请按照您认为适合您的任何顺序阅读!背景资料我正在为与 STA COM 通信的应用程序编写概念验证部分。这部分应用程序需要在单线程单元 (STA) 上下文中运行,以便与所述 STA COM 通信。应用程序的其余部分在 MTA 上下文中运行。当前状态到目前为止我想出的是创建一个包含循环的通信类,在 STA 中运行。while需要中继到 COM 对象的工作从外部排队到Communication类ConcurrentQueue。然后工作项在 while 循环中出列并执行工作。代码上下文交流类这是一个static类,包含一个旨在在 STA 状态下运行并检查是否需要由 COM 完成某些工作并将工作分派给处理程序的循环。
查看完整描述

2 回答

?
大话西游666

TA贡献1817条经验 获得超14个赞

汉斯做到了。SynchronizationContext 从技术上讲await,您的代码正在中断,因为. 但即使你写了一个,也不够。

这种方法的一个大问题是您的 STA 线程没有启动。STA 线程必须抽取 Win32 消息队列,否则它们就不是 STA 线程。SetApartmentState(ApartmentState.STA)只是告诉运行时这是一个 STA 线程;它不会使其成为 STA 线程。您必须泵送消息才能使其成为 STA 线程。

您可以自己编写消息泵,但我不知道有谁敢这样做。大多数人从WinForms(la Hans 的回答)WPF安装消息泵。也可以使用UWP 消息泵来执行此操作。

使用提供的消息泵的一个很好的副作用是它们还提供一个SynchronizationContext(例如WinFormsSynchronizationContextDispatcherSynchronizationContext),因此await可以自然地工作。此外,由于每个 .NET UI 框架都定义了一个“运行此委托”的 Win32 消息,因此底层 Win32 消息队列也可以包含您想要排队到您的线程的所有工作,因此显式队列及其“运行程序”代码不再是必要的。


查看完整回答
反对 回复 2022-12-24
?
湖上湖

TA贡献2003条经验 获得超2个赞

因为在await Task.Delay()语句之后,您的代码在 ThreadPool 线程之一内运行,并且由于 ThreadPool 线程在设计上是 MTA。


var th = new Thread(async () =>

        {

            var beforAwait = Thread.CurrentThread.GetApartmentState(); // ==> STA 


             await Task.Delay(1000);


            var afterAwait = Thread.CurrentThread.GetApartmentState(); // ==> MTA


        });


        th.SetApartmentState(ApartmentState.STA);

        th.Start();


查看完整回答
反对 回复 2022-12-24
  • 2 回答
  • 0 关注
  • 176 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号