292 Stimmen

Wie kann ich den Cursor in den Wartecursor verwandeln?

Wie kann ich dem Benutzer den Wait / Busy Cursor (normalerweise der Sanduhr) anzeigen, um ihm mitzuteilen, dass das Programm etwas ausführt?

4voto

Darrel Lee Punkte 2117

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

4voto

wenha Punkte 41

Okey, Die Ansichten anderer Personen sind sehr klar, aber ich möchte einige zusätzliche Punkte hinzufügen, wie folgt:

Cursor tempCursor = Cursor.Current;

Cursor.Current = Cursors.WaitCursor;

// Führen Sie zeitintensive Operationen durch         

Cursor.Current = tempCursor;

4voto

HEF Punkte 41

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

2voto

Georg Punkte 1668

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

2voto

Verwenden Sie dies mit WPF:

Cursor = Cursors.Wait;

// Ihre aufwändige Arbeit hier

Cursor = Cursors.Arrow;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X