web-dev-qa-db-ja.com

バックグラウンドワーカーの実行中に待機カーソルを表示する

Windowsアプリケーションの起動時に、アプリケーションにロードするデフォルトのデータを取得するために、Webサービスを呼び出す必要があります。フォームのロード中に、バックグラウンドワーカーを実行してこのデータを取得します。このデータが取得されるまで待機カーソルを表示したい。どうすればいいですか?

Backgroundworkerを呼び出す前に待機カーソルを設定してみました。進行状況を100と報告したら、デフォルトのカーソルに戻しました。待機カーソルが表示されますが、マウスを動かすとカーソルが消えます。

環境:

  • Windows 7 Pro 64ビット
  • VS2010 C#.NET 4.0
  • Windowsフォーム

編集:ジェイリッグスが提案した方法でカーソルを設定しています。マウスを動かさない場合にのみ機能します。

* * UPDATE:次のようなボタンクリックを作成しました。ボタンクリックをしてマウスを動かすと、マウスを動かしたかどうかに関係なく、待機カーソルが表示されます。

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

UseWaitCursorは機能しますか? (RunWorkerAsync()を呼び出す場合はtrueに設定し、完了イベントを呼び出す場合はfalseに設定します)。現在カーソルを設定するために何を使用していますか?

19
Mark Sowul

これに対して待機カーソルを表示しないでください。代わりに、フォームのコントロールを使用して、バックグラウンドワーカーが何かを行っていることを示します。待機カーソルは、UIスレッドが使用する適切なインジケーターです(ユーザーが何かに触れることができない/すべきではないことを示しているため)が、バックグラウンドで発生していることには適していません。

11
MusiGenesis

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

カーソルをデフォルトに戻すには、BGWの RunWorkerCompleted event を使用する必要があります。

編集:

BGWを起動する前に次のコードを呼び出して、カーソルが待機するように設定します。

this.Cursor = Cursors.WaitCursor;

BGWのRunWorkerCompletedイベントでカーソルをリセットします。

this.Cursor = Cursors.Default;
4
Jay Riggs

ここにはすでにたくさんの答えがありますが、私に役立つ別の解決策を見つけたので、それをリストに入れようと思いました。

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

私はこのように両方を並べて使用し、いつも期待通りに動作するように縫い合わせています。特に、ワ​​ーカーの実行中に待機カーソルを表示したい場合。これがまだ探している他の人を助けることを願っています。

2
Troublesum

MSフォーラムスレッド seWaitCursor not working but Cursor = Cursors.WaitCursor does ../Cursor.Current vs. this.Cursor

wFのUseWaitCursorの実装が、砂時計カーソルを表示するために実際に機能する機会を逃し、「using」ブロックで使用できるHourGlassクラスを表示することが確認されました

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

これが私が今やっていることです、この助けが欲しいです。

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

他の何かがカーソルを設定している必要があります。以下のコードは、タイマーの開始時に待機カーソルを設定し、タイマーの期限が切れるとカーソルを以前の値に戻します。これは期待どおりに機能します。待機カーソルは間隔全体に残ります。もちろん、フォームの外にカーソルを移動すると、マウスカーソルが置かれているウィンドウのカーソルが表示されますが、フォームに戻すと、待機カーソルが表示されます。

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;
    }
}
0
Jim Mischel

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は、上記の壊れたコードを使用した多くのコントロールの1つにすぎません。

しかし、WaitCursorが不要で、コントロールのユーザーが外部から設定したカーソルを維持したい場合はどうでしょうか。この場合、オプションは限られています。コントロールのユーザーが設定したカーソルを受け取るには、コントロールのCursorプロパティをオーバーライドする必要がありますORリフレクションを使用して内部カーソルにアクセスする必要がありますベースのControlクラスによって格納された値。その後、上記の最初のメソッドを使用して、カーソルのキャッシュと復元を行うことができます。*注:ベースの結果ではなく、コントロールのユーザーが設定した内部カーソル値をキャッシュする必要があります。カーソル!

0
deAtog