c# – 当使用STA和线程花费太长时,表现形式奇怪
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 当使用STA和线程花费太长时,表现形式奇怪,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2487字,纯文字阅读大概需要4分钟。
内容图文
![c# – 当使用STA和线程花费太长时,表现形式奇怪](/upload/InfoBanner/zyjiaocheng/811/9abe5e1efe4d4258954db31b8a934ef4.jpg)
我们正在用C#开发一个多线程游戏引擎,我们遇到了一个问题,我们需要STAThread属性(或者手动将我们的线程设置为STA)以启用拖放支持(如果没有STA,则不能设置AllowDrop).但是,当我们启用STA并且更新方法比draw方法花费的时间更长时(如下所示),窗口不再正常运行 – 当它在任务栏中单击时,它不会像您期望的那样最小化和最大化它.不同系统的确切行为是不同的,我猜这种竞争条件会起作用.
这是我们的测试代码:
[STAThread]
public static void Main()
{
Form form = new Form();
form.Show();
Barrier barrier = new Barrier(2);
Thread updateThread = new Thread(() => {
while (true)
{
barrier.SignalAndWait();
Thread.Sleep(30); //Update
barrier.SignalAndWait();
}
});
updateThread.Start();
while (true)
{
barrier.SignalAndWait();
Thread.Sleep(15); //Draw
barrier.SignalAndWait();
Application.DoEvents();
}
}
解决方法:
我意识到这个问题,我在一个非托管应用程序的Vista中调试了一个非常类似的问题.问题非常模糊,与您通过单击任务栏按钮生成的非常不稳定的WM_ACTIVATEAPP消息有关.特别是当它由嵌套的消息循环调度时,该循环进行消息过滤以仅允许分派某些“安全”消息.
它是由Barrier.SignalAndWait()调用引起的.这会阻止UI线程,这对于STA线程来说是非法的. CLR对此做了一些事情,它在没有信号通知底层同步对象的情况下泵送自己的消息循环.如果是那个调度WM_ACTIVATEAPP的循环,并且赔率非常高,因为你阻塞了30毫秒并且只抽了一次,那么它就出错了.由于一些神秘的原因,后续消息不会被分派.几乎肯定是由该消息循环完成的过滤引起的.否则很难看,该代码从未发布过,也无法反编译.
它是可以修复的,但不容易.解决方法是强制CLR不泵送此消息循环.哪个是好的,因为你的等待时间很短.你可以通过重写SynchronizationContext.Wait()方法做的事情.不幸的是,这很难做到,WindowsFormsSynchronizationContext类是密封的,因此无法派生来覆盖其Wait()方法.您需要访问Reference Source并将该类复制/粘贴到您的代码中.给它另一个名字.
我会给出它的简短版本,显示你需要改变的内容:
using System.Runtime.InteropServices;
class MySynchronizationContext : SynchronizationContext {
public MySynchronizationContext() {
base.SetWaitNotificationRequired();
}
public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) {
return WaitForMultipleObjects(waitHandles.Length, waitHandles, false, millisecondsTimeout);
}
[DllImport("kernel32.dll")]
static extern int WaitForMultipleObjects(int nCount, IntPtr[] lpHandles,
bool bWaitAll, int dwMilliseconds);
}
并安装新的同步提供程序:
System.ComponentModel.AsyncOperationManager.SynchronizationContext =
new MySynchronizationContext();
简而言之,SetWaitNotificationRequired()调用告诉CLR它应该调用Wait()覆盖而不是使用自己的Wait()实现.并且Wait()覆盖使用OS’阻塞等待而不进行其他泵送.当我测试并解决问题时工作得很好.
内容总结
以上是互联网集市为您收集整理的c# – 当使用STA和线程花费太长时,表现形式奇怪全部内容,希望文章能够帮你解决c# – 当使用STA和线程花费太长时,表现形式奇怪所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。