在backgroundworker运行时显示等待光标

在我的Windows应用程序启动期间,我必须调用Web服务来检索一些默认数据以加载到我的应用程序中。 在加载表单期间,我运行一个后台工作程序来检索这些数据。 我想显示等待光标,直到检索到这些数据。 我该怎么办?

我已经尝试在调用backgroundworker运行之前设置等待光标。 当我报告100的进度时,我将其设置回默认光标。 等待光标出现但是当我移动鼠标时它会消失。

环境:

  • Windows 7 Pro 64位
  • VS2010 C#.NET 4.0
  • Windows窗体

编辑:我按照Jay Riggs建议的方式设置光标。 它只有在我不移动鼠标时才有效。

* *更新:我创建了一个单击按钮,执行以下操作:当我按下按钮并单击并移动鼠标时,无论我是否移动鼠标,都会显示等待光标。

void BtnClick() { Cursor = Cursors.WaitCursor; Thread.Sleep(8000); Cursor = Cursors.Default; } 

如果我执行以下操作:我看到等待光标,当我移动鼠标时,它会消失在窗体内。 如果我移动到状态栏或菜单栏,则会出现等待光标。

 Cursor = Cursors.WaitCursor; if (!backgroundWorker.IsBusy) { backGroundWorker.RunWorkerAsync(); } void backGroundWorkerDoWork(object sender, DoWorkEventArgs e) { Thread.Sleep(8000); } void backGroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Cursor = Cursors.Default; } 

如果我执行以下操作:出现等待光标,当我移动鼠标时它仍然出现但在文本字段中移动时有时会闪烁。 虽然光标变为等待光标,但它不会阻止您单击任何内容。

 if (!backgroundWorker.IsBusy) { backGroundWorker.RunWorkerAsync(); } void backGroundWorkerDoWork(object sender, DoWorkEventArgs e) { UseWaitCursor = true; Thread.Sleep(8000); } void backGroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { UseWaitCursor = false; } 

UseWaitCursor吗? (调用RunWorkerAsync()时设置为true,调用完成事件时设置为false)。 你现在用什么来设置光标?

不要为此显示等待光标 – 而是使用表单上的控件来指示后台工作人员正忙着做某事。 等待光标是UI线程使用的适当指示器(因为它表示用户不能/不应该触摸任何东西),但它不适合在后台发生的事情。

在WPF中,我通过在启动Backgroundworker之前将Mouse.OverrideCursor属性设置为Cursors.Wait ,然后在RunWorkerCompleted事件中将其重置为null来完成此操作。 到目前为止似乎工作得很好。

 public void go() { BackgroundWorker thread = new BackgroundWorker(); thread.DoWork += run; thread.RunWorkerCompleted += taskCompleted; thread.WorkerReportsProgress = true; // Change mouse cursor to busy Mouse.OverrideCursor = Cursors.Wait; thread.RunWorkerAsync(); } private void taskCompleted(object sender, RunWorkerCompletedEventArgs e) { // Reset mouse cursor Mouse.OverrideCursor = null; } 

您应该使用BGW的RunWorkerCompleted事件将光标设置回默认值。

编辑:

在启动BGW之前,通过调用此代码将光标设置为等待:

 this.Cursor = Cursors.WaitCursor; 

通过以下方式重置BGW的RunWorkerCompleted事件中的光标:

 this.Cursor = Cursors.Default; 

在MS论坛中,线程UseWaitCursor不工作,但Cursor = Cursors.WaitCursor做 ../&Cursor.Current vs. this.Cursor

确认WF的UseWaitCursor实现错过了实际显示沙漏光标并显示HourGlass类的机会,可以与“使用”块一起使用

 using (new HourGlass()) { // Do something that takes time... System.Threading.Thread.Sleep(2000); } 

其他必须设置光标。 下面的代码在计时器启动时设置等待光标,然后在计时器到期后将光标设置回先前的值。 它按预期工作:等待光标在整个间隔内保持不变。 当然,将光标移动到窗体外会显示鼠标光标所在窗口的光标,但将其移回我的窗体会显示等待光标。

 public partial class MyDialog : Form { private Timer myTimer; public MyDialog() { InitializeComponent(); myTimer = new Timer(); myTimer.Tick += new EventHandler(myTimer_Tick); myTimer.Interval = 5000; myTimer.Enabled = false; } private Cursor SaveCursor; private void button1_Click(object sender, EventArgs e) { Cursor = Cursors.WaitCursor; myTimer.Enabled = true; } void myTimer_Tick(object sender, EventArgs e) { Cursor = SaveCursor; myTimer.Enabled = false; } } 

Microsoft Reference Source为我们提供了Control.UseWaitCursor和Control.Cursor的实现。 如果检查Control.Cursor,您将看到如果UseWaitCursor设置为True,Control.Cursor将返回Cursor.WaitCursor,无论控件上设置了什么游标。 由于此行为,无法缓存从Control.Cursor返回的值。

 // DON'T DO THIS: THIS CODE WILL BREAK IF UseWaitCursor IS SET TO TRUE // Store the original cursor Cursor cachedCursor = this.Cursor; // Set the cursor to a wait cursor. this.Cursor = Cursors.WaitCursor; // Perform some task // Restore the original cursor this.Cursor = cachedCursor; 

虽然上面看起来足够无害,但如果有人在执行之前将Control.UseWaitCursor设置为True,它会立即导致问题。 其结果将是一个卡住的等待游标,因为Control.Cursor在上面的第一行返回了Cursors.WaitCursor。 因此,更好的方法是更改​​光标:

 // Change the cursor as needed this.Cursor = Cursors.WaitCursor; // Perform some task // Restore the default cursor when finished. this.Cursor = this.DefaultCursor; 

对于绝大多数事情,上面应该足以在需要时显示等待光标。 但是,如果控件的子控件也修改了光标,则子控件设置的光标将覆盖在父控件上设置的光标。 IE如果在将光标设置为Cursors.WaitCursor的窗体上将标签的光标设置为Cursors.IBeam,则标签将在窗体显示WaitCursor时显示IBeam。 只有Control.Cursor返回与Control.DefaultCursor相同值的控件才会在这种情况下显示表单上的WaitCursor集。 这是Control.UseWaitCursor的用武之地。在表单上设置UseWaitCursor也会在其所有子项上设置UseWaitCursor。 只要表单上没有任何控件使用上面的破解代码。 DataGridView只是使用上面破坏的代码的众多控件之一。

但是..如果你不想要WaitCursor并且想要保持控件用户在外部设置光标怎么办? 在这种情况下,您的选项是有限的,您必须覆盖控件的Cursor属性以接收控件用户设置的游标,或者必须使用reflection来访问基本Control类存储的内部游标值。 然后,只有这样才能使用上面的第一种方法来缓存和恢复光标。 *注意:您必须缓存控件用户设置的内部游标值,而不是base.Cursor的结果!

这是我现在正在做的事情,我希望这有帮助。

 private void LoadWaitCursor() { this.Dispatcher.Invoke((Action)(() => { Mouse.OverrideCursor = Cursors.Wait; })); } private void LoadDefaultCursor() { this.Dispatcher.Invoke((Action)(() => { Mouse.OverrideCursor = null; })); } 

这里有很多答案,但我找到了另一个对我有用的解决方案,所以我想我列出它。

 private void ShowWaitCursor(){ Application.UseWaitCursor = true; //keeps waitcursor even when the thread ends. System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; //Normal mode of setting waitcursor } private void ShowNormalCursor(){ Application.UseWaitCursor = false; System.Windows.Forms.Cursor.Current = Cursors.Default; } 

我像这样使用它们并且接缝按照我期望的方式工作。 特别是当我想在工作人员运行时显示等待光标时。 希望这有助于其他人继续寻找。