【问题标题】:SetWindowPos even when the main thread is blocked?即使主线程被阻塞也设置窗口位置?
【发布时间】:2019-03-24 01:35:46
【问题描述】:
我试图让我的程序通过每 10 毫秒调用一次 SetWindowPos 来移动自己,以跟随光标。问题是,当我的程序的主线程被 Thread.Sleep() 阻塞时,窗口停止移动。
我将对 SetWindowPos 的调用放入辅助 System.Thread,但它仍然被阻止。看来 SetWindowPos 总是由拥有窗口的线程处理。所以如果我的主线程很忙,窗口就不能移动,即使请求是从不同的线程发出的。
是否有其他方法可以移动窗口,即使拥有窗口的线程很忙?谢谢!
【问题讨论】:
标签:
c#
multithreading
setwindowpos
【解决方案1】:
我不相信。所有 UI 操作必须在 GUI 应用程序中称为 UI 线程 的主应用程序线程上执行。是否为按钮点击事件;鼠标移动;滚动;绘制 等,包括移动窗口,这些操作在应用程序消息队列 中排队(有点像 Windows 为所有应用程序维护的 FIFO 缓冲区),必须由 UI 线程处理。
如果说一个按钮点击事件需要很长时间,因为程序员决定在与回调相同的线程中执行一个冗长的数据库操作,那么 UI 将冻结,直到回调完成,这恰好是数据库代码。
同样,如果您的 UI 线程代码中的某处有 Thread.Sleep(),那么 UI 也会在同一时间段内冻结。
替代方案
您可能需要考虑将冗长的操作移至另一个线程或采用简单的当代和推荐方式并使用async/await。这样做可以让您在不阻塞用户界面的情况下执行冗长的操作。
计时器
此外,请考虑使用Timer 代替Thread.Sleep() 或等效的替代方法来代替每秒移动窗口100 次。请务必为 GUI 应用程序使用正确的计时器,因为 .NET 定义了至少四 (4) 个我相信并且并非所有默认情况下适合 (如果有的话)适用于 GUI 应用程序。