Wie kann ich dem Benutzer den Wait / Busy Cursor (normalerweise der Sanduhr) anzeigen, um ihm mitzuteilen, dass das Programm etwas ausführt?
Antworten
Zu viele Anzeigen?Also habe ich eine statische async Methode erstellt. Das deaktiviert die Steuerung, die die Aktion startet und ändert den Anwendungscursor. Es führt die Aktion als Task aus und wartet darauf, dass sie beendet wird. Die Steuerung kehrt zum Aufrufer zurück, während sie wartet. So bleibt die Anwendung reaktionsfähig, auch wenn das Busy-Symbol sich dreht.
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;
}
Hier ist der Code des Hauptformulars
private void btnSleep_Click(object sender, EventArgs e)
{
var control = sender as Control;
if (control != null)
{
Log.Info("Starte langwierigen Vorgang...");
CursorWait.LengthyOperation(control, () => DummyAction());
Log.Info("...Langwieriger Vorgang gestartet.");
}
}
private void DummyAction()
{
try
{
var _log = NLog.LogManager.GetLogger("TmpLogger");
_log.Info("Aktion - Schlafen");
TimeSpan sleep = new TimeSpan(0, 0, 16);
Thread.Sleep(sleep);
_log.Info("Aktion - Aufwachen");
}
finally
{
}
}
Ich musste einen separaten Logger für die Dummy-Aktion verwenden (ich verwende Nlog) und mein Hauptlogger schreibt in die Benutzeroberfläche (ein Rich Text Box). Ich konnte den Busy-Cursor nicht nur anzeigen, wenn er über einem bestimmten Container im Formular war (aber ich habe es nicht sehr stark versucht.) Alle Steuerelemente haben eine UseWaitCursor-Eigenschaft, aber es scheint keine Auswirkung auf die von mir ausprobierten Steuerelemente zu haben (vielleicht weil sie nicht oben waren?)
Hier ist das Hauptprotokoll, das die Dinge in der erwarteten Reihenfolge zeigt:
16:51:33.1064 Starte langwierigen Vorgang...
16:51:33.1215 Task Start
16:51:33.1215 Before Await
16:51:33.1215 ...Langwieriger Vorgang gestartet.
16:51:49.1276 After await
16:51:49.1537 Finally
Für Windows Forms-Anwendungen kann es sehr nützlich sein, die Option zum Deaktivieren einer UI-Steuerelement zu haben. Also sieht mein Vorschlag so aus:
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;
}
}
Verwendung:
private void UiControl_Click(object sender, EventArgs e)
{
using (new AppWaitCursor(sender))
{
LanglaufendeFunktion();
}
}
Mit der Klasse unten können Sie den Vorschlag von Donut "ausnahmesicher" machen.
using (new CursorHandler())
{
// Führen Sie Ihren zeitaufwändigen Hashing-Code hier aus...
}
die Klasse CursorHandler
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;
}
- See previous answers
- Weitere Antworten anzeigen