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