Yanıtlar:
Kullanabilirsiniz Cursor.Current
.
// Set cursor as hourglass
Cursor.Current = Cursors.WaitCursor;
// Execute your time-intensive hashing code here...
// Set cursor as default arrow
Cursor.Current = Cursors.Default;
Ancak, karma işlemi gerçekten uzunsa (MSDN bunu 2-7 saniyeden fazla olarak tanımlar), kullanıcıyı ilerlemeyi bildirmek için imleç dışında görsel bir geri bildirim göstergesi kullanmanız gerekir. Daha ayrıntılı yönergeler için bu makaleye bakın .
Düzenleme:
@Am belirttiği gibi , kum saati gerçekten görüntülendiğinden emin olmak için Application.DoEvents();
sonra çağırmanız gerekebilir Cursor.Current = Cursors.WaitCursor;
.
Application.UseWaitCursor = true
veApplication.UseWaitCursor = false
Aslında,
Cursor.Current = Cursors.WaitCursor;
Bekle imlecini geçici olarak ayarlar, ancak Bekle imlecinin işleminizin sonuna kadar gösterilmesini sağlamaz. Programınızdaki diğer programlar veya kontroller, işlem devam ederken fareyi hareket ettirdiğinizde olduğu gibi imleci varsayılan oka kolayca sıfırlayabilir.
Bekle imlecini göstermenin çok daha iyi bir yolu, bir formdaki UseWaitCursor özelliğini true olarak ayarlamaktır:
form.UseWaitCursor = true;
Bu, siz bu özelliği false değerine ayarlayana kadar formdaki tüm denetimler için bekleme imlecini görüntüler. Bekle imlecinin Uygulama düzeyinde gösterilmesini istiyorsanız şunları kullanmalısınız:
Application.UseWaitCursor = true;
Bir öncekine dayanarak, tercih ettiğim yaklaşım (bu sık gerçekleştirilen bir eylem olduğu için) bekleme imleci kodunu IDisposable yardımcı sınıfına sarmaktır, böylece () (bir kod satırı) ile kullanılabilir, isteğe bağlı parametreler alır, çalıştırılır içindeki kodu girin ve daha sonra temizleyin (imleci geri yükle).
public class CursorWait : IDisposable
{
public CursorWait(bool appStarting = false, bool applicationCursor = false)
{
// Wait
Cursor.Current = appStarting ? Cursors.AppStarting : Cursors.WaitCursor;
if (applicationCursor) Application.UseWaitCursor = true;
}
public void Dispose()
{
// Reset
Cursor.Current = Cursors.Default;
Application.UseWaitCursor = false;
}
}
Kullanımı:
using (new CursorWait())
{
// Perform some code that shows cursor
}
UseWaitCursor öğesini Form veya Pencere düzeyinde kullanmak daha kolaydır . Tipik bir kullanım durumu aşağıdaki gibi görünebilir:
private void button1_Click(object sender, EventArgs e)
{
try
{
this.Enabled = false;//optional, better target a panel or specific controls
this.UseWaitCursor = true;//from the Form/Window instance
Application.DoEvents();//messages pumped to update controls
//execute a lengthy blocking operation here,
//bla bla ....
}
finally
{
this.Enabled = true;//optional
this.UseWaitCursor = false;
}
}
Daha iyi bir kullanıcı arayüzü deneyimi için Asynchrony'yi farklı bir iş parçacığından kullanmalısınız.
Benim yaklaşımım, tüm hesaplamaları bir arka plan çalışanında yapmak olacaktır.
Sonra imleci şu şekilde değiştirin:
this.Cursor = Cursors.Wait;
Ve iş parçacığının bitiş etkinliğinde imleci geri yükleyin:
this.Cursor = Cursors.Default;
Bu, belirli kontroller için de yapılabilir, bu nedenle imleç yalnızca fare üstlerinde olduğunda kum saati olacaktır.
Tamam bu yüzden statik bir zaman uyumsuzluk yöntemi oluşturdum. Bu, eylemi başlatan ve uygulama imlecini değiştiren denetimi devre dışı bırakır. Eylemi bir görev olarak yürütür ve bitmesini bekler. Kontrol beklerken arayana geri döner. Böylece meşgul simgesi dönse bile uygulama yanıt verir.
async public static void LengthyOperation(Control control, Action action)
{
try
{
control.Enabled = false;
Application.UseWaitCursor = true;
Task doWork = new Task(() => action(), TaskCreationOptions.LongRunning);
Log.Info("Task Start");
doWork.Start();
Log.Info("Before Await");
await doWork;
Log.Info("After await");
}
finally
{
Log.Info("Finally");
Application.UseWaitCursor = false;
control.Enabled = true;
}
İşte ana formu oluşturan kod
private void btnSleep_Click(object sender, EventArgs e)
{
var control = sender as Control;
if (control != null)
{
Log.Info("Launching lengthy operation...");
CursorWait.LengthyOperation(control, () => DummyAction());
Log.Info("...Lengthy operation launched.");
}
}
private void DummyAction()
{
try
{
var _log = NLog.LogManager.GetLogger("TmpLogger");
_log.Info("Action - Sleep");
TimeSpan sleep = new TimeSpan(0, 0, 16);
Thread.Sleep(sleep);
_log.Info("Action - Wakeup");
}
finally
{
}
}
Ben kukla eylem (Nlog kullanıyorum) için ayrı bir logger kullanmak zorunda kaldı ve benim ana logger UI (zengin bir metin kutusu) yazıyor. Meşgul imleci yalnızca formdaki belirli bir kapsayıcı üzerinde zaman elde edemedim (ama çok denemedim.) Tüm denetimlerin bir UseWaitCursor özelliği var, ancak denetimleri üzerinde herhangi bir etkisi yok gibi görünüyor Denedim (belki de üstte olmadıkları için?)
Beklediğiniz sırayla olan şeyleri gösteren ana günlük:
16:51:33.1064 Launching lengthy operation...
16:51:33.1215 Task Start
16:51:33.1215 Before Await
16:51:33.1215 ...Lengthy operation launched.
16:51:49.1276 After await
16:51:49.1537 Finally
Aşağıdaki sınıf ile Donut "istisna güvenli" önerisini yapabilirsiniz.
using (new CursorHandler())
{
// Execute your time-intensive hashing code here...
}
CursorHandler sınıfı
public class CursorHandler
: IDisposable
{
public CursorHandler(Cursor cursor = null)
{
_saved = Cursor.Current;
Cursor.Current = cursor ?? Cursors.WaitCursor;
}
public void Dispose()
{
if (_saved != null)
{
Cursor.Current = _saved;
_saved = null;
}
}
private Cursor _saved;
}
Windows Forms uygulamaları için, bir UI-Control'ün isteğe bağlı olarak devre dışı bırakılması çok yararlı olabilir. Benim önerim şöyle:
public class AppWaitCursor : IDisposable
{
private readonly Control _eventControl;
public AppWaitCursor(object eventSender = null)
{
_eventControl = eventSender as Control;
if (_eventControl != null)
_eventControl.Enabled = false;
Application.UseWaitCursor = true;
Application.DoEvents();
}
public void Dispose()
{
if (_eventControl != null)
_eventControl.Enabled = true;
Cursor.Current = Cursors.Default;
Application.UseWaitCursor = false;
}
}
Kullanımı:
private void UiControl_Click(object sender, EventArgs e)
{
using (new AppWaitCursor(sender))
{
LongRunningCall();
}
}
WPF ile kullanın:
Cursor = Cursors.Wait;
// Your Heavy work here
Cursor = Cursors.Arrow;