在backgroundworker运行时显示等待光标

时间:2011-02-25 21:09:42

标签: c# cursor backgroundworker wait

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

我已经尝试在调用后台工作程序之前设置等待光标。当我报告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;
}

9 个答案:

答案 0 :(得分:18)

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

答案 1 :(得分:11)

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

答案 2 :(得分:6)

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

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;
}

答案 3 :(得分:4)

你应该使用BGW的RunWorkerCompleted event将光标设置回默认值。

修改

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

this.Cursor = Cursors.WaitCursor;

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

this.Cursor = Cursors.Default;

答案 4 :(得分:1)

在MS论坛帖子UseWaitCursor not working but Cursor = Cursors.WaitCursor does../& Cursor.Current vs. this.Cursor

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

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

答案 5 :(得分:0)

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

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;
    }
}

答案 6 :(得分:0)

Microsoft Reference Source为我们提供了Control.UseWaitCursorControl.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属性以接收控件用户设置的游标,或者必须使用反射来访问基本Control类存储的内部游标值。然后,只有这样才能使用上面的第一个方法来缓存和恢复光标。 *注意:您必须缓存控件用户设置的内部游标值,而不是base.Cursor的结果!

答案 7 :(得分:0)

以下是我现在正在做的事情,希望能有所帮助。

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

答案 8 :(得分:0)

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

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;
}

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