繁体   English   中英

在backgroundworker运行时显示等待光标

[英]Displaying wait cursor in while backgroundworker is running

在我的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);
      }

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的结果!

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM