鼠标移动和线程

发布于 2024-10-10 05:54:28 字数 906 浏览 0 评论 0原文

当我将鼠标移到窗口上时,程序运行得更快(cc. 3 倍)。这是在 MacBook 上运行的实时网络摄像头 .Net/Mono 应用程序。在 Windows 上完美运行。这可能是笔记本电脑的省电功能吗?代码:

Thread t = new Thread(Foo);
t.Priority = ThreadPriority.Highest; // I've tried without priority too, doesn't matter
t.Start();
...
delegate void SetInt(int k);
void Foo()
{
    int k = 0;
    while (true)
    {
        ++k; 
        BeginInvoke(new SetInt(Bar), k);   
    }
}
void Bar(int k)
{
    Graphics.FromImage(pictureBox1.Image).DrawString(k.ToString(),
        System.Fonts.DefaultFont, Brushes.Red, 0, 0);
    pictureBox1.Invalidate();
}

我观察k的值。它每秒增加 10-30 次,具体取决于鼠标移动。看起来 UI 线程阻塞了工作线程?工作线程应在一秒内递增 k 万次。

编辑: Miguel de Icaza 怀疑这是 Mono 中的一个错误。我将其上传到 Mono 的 bugtracker: https://bugzilla.novell.com/show_bug.cgi?id=663433 附测试用例。现在我正在寻找一种破解方法来避免这个问题。

When I move the mouse over the window, the program runs much faster (cc. 3 times). This is a real time webcam .Net/Mono application running on a MacBook. On Windows works perfectly. Is this maybe a power saving function of the laptop? The code:

Thread t = new Thread(Foo);
t.Priority = ThreadPriority.Highest; // I've tried without priority too, doesn't matter
t.Start();
...
delegate void SetInt(int k);
void Foo()
{
    int k = 0;
    while (true)
    {
        ++k; 
        BeginInvoke(new SetInt(Bar), k);   
    }
}
void Bar(int k)
{
    Graphics.FromImage(pictureBox1.Image).DrawString(k.ToString(),
        System.Fonts.DefaultFont, Brushes.Red, 0, 0);
    pictureBox1.Invalidate();
}

I watch the value of k. It is incremented 10-30 times a sec, depending on the mouse movement. It looks like the UI thread blocks the worker thread? The worker thread should increment k million times in a sec.

Edit: Miguel de Icaza suspects this is a bug in Mono. I uploaded it to Mono's bugtracker:
https://bugzilla.novell.com/show_bug.cgi?id=663433
Test case is attached. Now I'm searching for a hack to avoid the problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蘸点软妹酱 2024-10-17 05:54:28

不同的操作系统以不同的方式对待线程优先级,并且您不能依赖它们在不同操作系统上以相同的方式工作。您甚至不能依赖它们在不同虚拟机(Mono 与 .net)上以相同的方式工作,因为这些是操作系统相关的值,并不是由规范真正定义的。

Different OS's treat thread priority differently, and you cannot depend on them working the same way on different OS's. You can't even depend on them working the same way across different Virtual Machines (Mono vs .net), because these are OS dependant values and not really defined by the specification.

吃→可爱长大的 2024-10-17 05:54:28

我对此进行了研究,并相信我已经找到了解决方法。我在 Mono 上运行的 C# .Net 程序中遇到了同样的问题,其中消息未在线程中处理。问题似乎在于线程没有被调用或等待事件。我发现的解决方法如下。

1)创建一个表单事件(注意它与System.Timers不同)

private System.Windows.Forms.TimertimerForMonoResponsiveness;

2)在构造函数或初始化中设置表单事件

// This is a fix for mono not updating messages until an event (such as movement of
// the mouse) happens
// We use an event timer to fire off an event on a regular basis.
// This calls a function that doesn't do anything.
if (Type.GetType("Mono.Runtime") != null) // Only run if in Mono
{
    this.timerForMonoResponsiveness = new System.Windows.Forms.Timer(this.components);
    this.timerForMonoResponsiveness.Interval = 100;
    this.timerForMonoResponsiveness.Tick += new EventHandler(timertimerForMonoResponsiveness_Tick);
    this.timerForMonoResponsiveness.Start();
}

注意:“< strong>this.components”在表单的 Form.designer.cs 中定义(应该自动完成),我的看起来像这样:

private System.ComponentModel.IContainer components = null;

它初始化为:

this.components = new System.ComponentModel.Container();

3)创建勾号定时器的功能

// This function executes a Tick event so the UI updates on Mono
// This is a Mono bug workaround as the message processing was not being processed
// and was waiting on invoke which on Mono only runs when a UI element is changed (or  
// the mouse is moved). This function therefore runs regularly to mitigate this issue 
// it is called within a Mono check and will not run on Windows
// The function is SUPPOSED TO DO NOTHING.

private void timerForMonoResponsiveness_Tick(object sender, EventArgs e)
{
    this.timerMonoEventForMessagesToBeUpdated.Stop();
    // This doesn't need to do anything, just call the event
    this.timerMonoEventForMessagesToBeUpdated.Start();          
}

希望这有帮助。

I looked into this, and believe I have found a workaround. I had the same issue with a program in C# .Net running on Mono where messages weren't being processed in a thread. It seems the issue is with the thread not getting invoked or waiting for an event. The work around I found is as follows.

1) Create a form event (note it is different to System.Timers)

private System.Windows.Forms.Timer timerForMonoResponsiveness;

2) Set up the form event in the Constructor or Initialization

// This is a fix for mono not updating messages until an event (such as movement of
// the mouse) happens
// We use an event timer to fire off an event on a regular basis.
// This calls a function that doesn't do anything.
if (Type.GetType("Mono.Runtime") != null) // Only run if in Mono
{
    this.timerForMonoResponsiveness = new System.Windows.Forms.Timer(this.components);
    this.timerForMonoResponsiveness.Interval = 100;
    this.timerForMonoResponsiveness.Tick += new EventHandler(timertimerForMonoResponsiveness_Tick);
    this.timerForMonoResponsiveness.Start();
}

NOTE: the "this.components" is defined in the Form.designer.cs of the form (should be done automatically) mine looks like this:

private System.ComponentModel.IContainer components = null;

It is initialized as:

this.components = new System.ComponentModel.Container();

3) Create the tick function for the timer

// This function executes a Tick event so the UI updates on Mono
// This is a Mono bug workaround as the message processing was not being processed
// and was waiting on invoke which on Mono only runs when a UI element is changed (or  
// the mouse is moved). This function therefore runs regularly to mitigate this issue 
// it is called within a Mono check and will not run on Windows
// The function is SUPPOSED TO DO NOTHING.

private void timerForMonoResponsiveness_Tick(object sender, EventArgs e)
{
    this.timerMonoEventForMessagesToBeUpdated.Stop();
    // This doesn't need to do anything, just call the event
    this.timerMonoEventForMessagesToBeUpdated.Start();          
}

Hope this helps.

長街聽風 2024-10-17 05:54:28

考虑到您在 Mac 上的 Mono 上运行此程序,我认为 CLR 没有获得完全优先级,或者线程没有获得完全优先级。在这里我同意神秘人的观点,你的优先级声明可能没有达到预期的效果。

此外,Windows 7 似乎还优化了前台进程,赋予它们更高的优先级,因此 UI 看起来响应更快,而 macOS 可能做得有点太多了。因此,当您的应用程序中发生活动(鼠标移动,也许按下键盘)时,您的应用程序将获得更多的处理器时间。

可能是 Mono 没有处理优先级,或者在运行时(操作系统本身)有什么东西改变了您的优先级。

Considering youre running this on Mono on a mac, i'm thinking the CLR isn't getting full priority or the thread isnt getting full priority. Here I agree with mystere man, your Priority statement may not be having the desired effect.

Also Windows 7 seems to optimize foreground processes to give them a higher priority so the UI seems more responsive, and the mac OS may be doing that a little too much. Therefore when activity occurs in your application (mouse movements and maybe keyboard presses) your application is given more processor time..

Could be Mono is not handling the priority or somethign is changing your priority during runtime (the OS iteself).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文