如何在WinForms中测试[STAThread]的性能影响?

Mat*_*Mut -1 .net c# com performance winforms

我设法在C#中编写了一个相对较大的WinForms应用程序,它在没有方法[STAThread]属性的情况下正常运行Main().

为了实现这一点,我必须覆盖很多WinForms功能(例如使用自定义BeginInvokeInvoke函数),使用自定义消息循环代替Application.Run,使用自定义文件对话框代替OpenFileDialogSaveFileDialog,并使用WM_DROPFILES进行拖放而不是WinForms开箱即用的OLE方法.这都是"科学".

现在我想测试从所有GUI线程中省略STAThreadAttribute对性能的任何影响.我对Control类内部使用的COM配置知之甚少,无法预测这种影响.执行速度可能取决于哪个线程正在调用内部COM对象Control.

不可否认,我无法提出可以测试性能影响的基准测试[STAThread],因为我不确定哪些功能/操作会受到这种变化的影响(特别是与Control课程有关).

我该怎么找?如果有的话,Control我应该通过省略哪些操作/方法运行得更快/更慢[STAThread]

附录:基本原理是我正在慢慢迁移我的应用程序以使用自定义窗口系统(出于可移植性的原因,主要是因为在Linux上使用Mono,其WinForms实现并不完整),所以我不得不自己重写很多功能.仅仅是巧合,我注意到我已经覆盖了如此多的功能,我可以省略[STAThread],一切都会按预期工作.

我期望由于COM编组调用ThreadPool(配置为MTA)和GUI线程(默认情况下应配置为STA)导致性能发生变化.ThreadPool由于在不同的线程公寓中配置了来自GUI线程的调用,因此需要进行编组,这会引入同步开销.通过将GUI线程保留为MTA,应该减少编组,因此可能更快地执行函数调用.我想以务实的方式测试这个主张.

Han*_*ant 7

[STAThread]附有太多的神秘感.但在实践中很简单,你做出承诺.穿过你的心,希望死去.您向操作系统承诺,您的主线程是一个热情好客的主页,用于不是线程安全的代码.保持承诺需要有一个调度程序(Application.Run)并且永远不会阻塞该线程.你以后做的事情,这就是你必须预先做出承诺的原因.

在Windows上运行的GUI应用程序中,总会有很多代码.无论您使用什么框架,这些代码的位置都更明显.但是更糟糕的东西是你看不到的代码.在UI自动化代码中,在希望通过剪贴板提供数据的应用程序中,或者在使用SetWindowsHookEx安装的挂钩中拖放,在具有视觉障碍的用户的屏幕阅读器中,在期望PostMessage的ActiveX组件中的类型上班.这样的代码不具备是线程安全的,操作系统不要求它是,主要是因为任何人写的代码有没有办法对它进行测试.他不知道你的应用程序的bean.

它对操作系统很重要,因为当这些代码不在 UI线程上运行时,它必须做一些事情.由于代码明确宣布它不是线程安全的,或者不必是,它必须保持代码安全.唯一可能的方法是初始化代码并在同一个线程上进行任何将来的调用.这需要一些技巧,代码必须被编组,使其在另一个线程上运行,具有调度程序循环对于使其工作至关重要.调度员是生产者 - 消费者问题的通用解决方案.

但是如果从正确的线程初始化代码,那么这不是必需的.操作系统如何知道它是否是"正确的线程"?[STAThread]承诺告诉它.

因此,您可以做出的第一个结论是不标记UI线程,因为STA实际上使您的程序变慢.因为每次通话都是编组的.不是唯一的问题,有很多这样的代码无法编组.作者必须做额外的工作来启用它,他必须提供代理/存根.有时它太难了,往往他根本就没有,因为他依靠你做得对.所以电话会失败.但这种情况发生在外部代码中,你不会发现.所以东西不起作用.或死锁.或者预期的事件不会被提升.悲惨的东西.您必须使用[STAThread]来避免痛苦.

这是一个纯粹的Windows实现细节,它在Unix上不存在.如果有的话,他们提供这些功能的方式完全不同.所以[STAThread]并不意味着在这样的操作系统上有任何意义,并且测试没有它会发生什么事情并不能告诉你什么.