Подтвердить что ты не робот

Отображение курсора ожидания во время работы фонового рабочего

Во время запуска моего приложения Windows я должен позвонить в веб-службу, чтобы получить некоторые данные по умолчанию для загрузки в мое приложение. Во время загрузки формы я запускаю фонового работника для извлечения этих данных. Я хочу отобразить курсор ожидания до тех пор, пока эти данные не будут восстановлены. Как мне это сделать?

Я попробовал установить курсор ожидания перед вызовом фонового рабочего. Когда я сообщаю о ходе 100, я возвращаю его по умолчанию. Курсор ожидания появляется, но когда я перемещаю мышь, он исчезает.

Окружающая среда:

  • 64-разрядная версия Windows 7 Pro
  • VS2010 С#.NET 4.0
  • Windows Forms

EDIT: Я настраиваю курсор так, как предположил Джей Риггс. Он работает только в том случае, если я не перемещаю мышь.

* * 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;
}
4b9b3361

Ответ 1

Работает ли UseWaitCursor? (Установите значение true при вызове RunWorkerAsync() и false при вызове события завершения). Что вы сейчас используете, чтобы установить курсор?

Ответ 2

Не показывать курсор ожидания для этого - вместо этого используйте элемент управления в форме, чтобы указать, что фоновой рабочий занят чем-то занятым. Курсор ожидания является подходящим индикатором для используемого потока пользовательского интерфейса (поскольку он указывает, что пользователь не может/не должен касаться чего-либо), но он не подходит для чего-то, происходящего в фоновом режиме.

Ответ 3

В WPF я сделал это, установив свойство Mouse.OverrideCursor в Cursors.Wait, прежде чем запускать Backgroundworker, а затем сбросив его на 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;
}

Ответ 4

Вы должны использовать BGW событие RunWorkerCompleted, чтобы вернуть курсор к значению по умолчанию.

EDIT:

Настройте курсор для ожидания, вызывая этот код перед запуском BGW:

this.Cursor = Cursors.WaitCursor;

Reset ваш курсор в событии BGW RunWorkerCompleted:

this.Cursor = Cursors.Default;

Ответ 5

В форуме 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);
      }

Ответ 6

Что-то еще нужно установить курсором. Приведенный ниже код устанавливает курсор ожидания при запуске таймера и затем возвращает курсор к предыдущему значению после истечения таймера. Он работает так, как ожидалось: курсор ожидания остается на протяжении всего интервала. Конечно, перемещение курсора за пределы формы покажет курсор для любого окна, в котором находится курсор мыши, но перемещение его обратно в мою форму показывает курсор ожидания.

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

Ответ 7

Справочный источник Microsoft дает нам реализацию 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.IBeam в форме, которая устанавливает его курсор в Cursors.WaitCursor, метка будет отображать IBeam, пока форма отображает WaitCursor. Только элементы управления, в которых Control.Cursor возвращает то же значение, что и Control.DefaultCursor, отображает в этом случае набор WaitCursor. Здесь находится Control.UseWaitCursor. Установка UseWaitCursor на форме устанавливает UseWaitCursor и для всех его дочерних элементов. Пока ни один из элементов управления формы не использует сломанный код выше. DataGridView является лишь одним из многих элементов управления, которые использовали сломанный код выше.

Но.. что, если вы не хотите WaitCursor и хотите сохранить курсор, установленный внешним пользователем пользователя? В этом случае ваши параметры ограничены, вы должны переопределить свойство Cursor вашего элемента управления, чтобы получить курсор, установленный пользователем вашего элемента управления. Или вы должны использовать отражение, чтобы получить доступ к внутреннему значению курсора, сохраненному базовым классом Control. Затем, и только тогда вы можете использовать первый метод выше для кеширования и восстановления курсора. * Примечание: вы должны кэшировать значение внутреннего курсора, заданное пользователем вашего элемента управления, а не результат базы. Курсор!

Ответ 8

Вот что я делаю сейчас, надеюсь эта помощь.

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

Ответ 9

Здесь уже много ответов, но я нашел другое решение, которое сработало для меня, поэтому я решил, что перечислил его.

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

Я использую оба в строке, как это, и это швы, чтобы работать так, как я ожидаю все время. Особенно, когда я хочу, чтобы указатель ожидания показывался во время работы рабочего. Надеюсь, это поможет кому-то еще по-прежнему смотреть.