簡體   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