[英]Displaying wait cursor in while backgroundworker is running
在我的Windows應用程序啟動期間,我必須調用Web服務來檢索一些默認數據以加載到我的應用程序中。 在加載表單期間,我運行后台工作程序來檢索此數據。 我想顯示等待光標,直到檢索到這些數據。 我該怎么做?
我已經嘗試在調用backgroundworker運行之前設置等待光標。 當我報告100的進度時,我將其設置回默認光標。 等待光標出現但是當我移動鼠標時它會消失。
環境:
編輯:我按照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.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只是使用上面破壞的代碼的眾多控件之一。
但是..如果你不想要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.