Frage

C # 2008

Ich bin mit dem Code unten an einem Softphone anmelden. Allerdings ist der Login progess ein langer Prozess, da es viele Dinge gibt, die initialisiert werden müssen und prüft gemacht werden, ich habe nur ein paar hier gesetzt haben, wie es um den Code zu lange machen würde zu schreiben.

Im Code unten ich, wenn die CancellationPending bin Überprüfung, ob die CancelAsync meines aufgerufen wurden in Schaltfläche klicken Ereignis abbrechen, bevor jede Kontrolle zu tun. Ist das richtig? Auch wenn die Überprüfung fehlschlägt Ich nenne auch die CancelAsync und stellen Sie die e.Cancel auf true gesetzt.

Ich würde gerne wissen, ob meine Methode, die ich hier verwendet habe, ist die beste Methode zu verwenden.

Vielen Dank für jede Beratung,

private void bgwProcessLogin_DoWork(object sender, DoWorkEventArgs e)
    {   
        /*
         * Perform at test to see if the background worker has been
         * cancelled by the user before attemping to continue to login.
         * 
         * Cancel background worker on any failed attemp to login
         */

        // Start with cancel being false as to reset this if cancel has been set to true
        // in the cancel button.
        e.Cancel = false;

        NetworkingTest connection_test = new NetworkingTest();
        if (!this.bgwProcessLogin.CancellationPending)
        { 
            // Check local LAN or Wireless connection               
            if (!connection_test.IsNetworkConnected())
            {
                // Update label
                if (this.lblRegistering.InvokeRequired)
                {
                    this.lblRegistering.Invoke(new UpdateRegisterLabelDelegate(UpdateRegisterLabel), "No network connection");
                }
                else
                {
                    this.lblRegistering.Text = "No network connection";
                }
                // Failed attemp
                this.bgwProcessLogin.CancelAsync();
                e.Cancel = true;
                return;
            }
            // Report current progress
            this.bgwProcessLogin.ReportProgress(0, "Network connected");
        }
        else
        {
            // User cancelled 
            e.Cancel = true;
            return;
        }

        // Test if access to Server is available
        if (!this.bgwProcessLogin.CancellationPending)
        {
            if (!connection_test.IsSIPServerAvailable())
            {
                // Update label
                if (this.lblRegistering.InvokeRequired)
                {
                    this.lblRegistering.Invoke(new UpdateRegisterLabelDelegate(UpdateRegisterLabel), "Server unavailable");
                }
                else
                {
                    this.lblRegistering.Text = "Server unavailable";
                }
                // Failed attemp
                this.bgwProcessLogin.CancelAsync();
                e.Cancel = true;
                return;
            }
            // Report current progress
            this.bgwProcessLogin.ReportProgress(1, "Server available");
        }
        else
        {
            // User cancelled 
            e.Cancel = true;
            return;
        }
        .
        .
        .
}


 private void bgwProcessLogin_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {   
        // Check for any errors
        if (e.Error == null)
        {
            if (e.Cancelled)
            {
                // User cancelled login or login failed                
            }
            else
            {
                // Login completed successfully                
            }
        }
        else
        {
            // Something failed display error
            this.statusDisplay1.CallStatus = e.Error.Message;
        }
    }


 private void bgwProcessLogin_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.lblRegistering.Text = e.UserState.ToString();
    }

private void btnCancel_Click(object sender, EventArgs e)
    {
        // Cancel the logging in process
        this.bgwProcessLogin.CancelAsync();
        this.lblRegistering.Text = "Logged out";
}
War es hilfreich?

Lösung

Es ist vielleicht nur ein Problem: wenn eine der Operation in DoWork Ereignishandler für eine lange Zeit dauern würde. In diesem Fall könnten Sie Ihre anstehende Operation abbrechen darf erst nach dieser Operation beendet. Wenn alle Operationen in DoWork Ereignisse nicht sehr lange dauern können (zum Beispiel nicht mehr als 5 Sekunden), seine ganz in Ordnung, aber wenn eine der Operationen kann für lange Zeit (5 Minuten, zum Beispiel) in diesem Fall Benutzern der letzte Mal hat zu warten, bis dieser Vorgang abgeschlossen.

Wenn DoWork lang anhaltende Operationen enthält, die Sie so etwas wie AbortableBackgroundWorker verwenden können. So etwas wie folgt aus:

public class AbortableBackgroundWorker : BackgroundWorker
{
    private Thread workerThread;

    protected override void OnDoWork(DoWorkEventArgs e)
    {
        workerThread = Thread.CurrentThread;
        try
        {
            base.OnDoWork(e);
        }
        catch (ThreadAbortException)
        {
            e.Cancel = true; //We must set Cancel property to true!
            Thread.ResetAbort(); //Prevents ThreadAbortException propagation
        }
    }


    public void Abort()
    {
        if (workerThread != null)
        {
            workerThread.Abort();
            workerThread = null;
        }
    }
}

In diesem Fall können Sie anstehende Operationen wirklich abbrechen können, aber Sie haben auch einige Einschränkungen (für weitere Informationen über verwalteten Thread abgebrochen und einige Einschränkungen finden Sie unter Klempner die Tiefen des Threadabort Mit Rotor ).

P. S. Ich stimme mit Oliver, dass Sie InvokeRequired in brauchbarer Form wickeln sollte.

Andere Tipps

Sie es den richtigen Weg machen, glaube ich. Sie Thread-Mitglieder finden, die Sie erlauben, einen Thread zu beenden oder abbrechen, aber man will sich nicht, wie dies für etwas verwenden. Es könnte ein wenig seltsam aussieht all „abgebrochen“ Kontrollen im Code zu haben, aber das kann Sie genau steuern, wenn Sie Ihren Faden verlassen. Wenn Sie waren „unsanft“, um den Worker-Thread abbrechen, hat der Thread keine Kontrolle über, wenn es austritt, und es könnte Zustand beschädigt werden.

Innerhalb Ihres DoWork () Funktion, die Sie ... schrieb. Je nachdem, wie viele Aufgaben der gleichen Struktur wie die angezeigten zwei ein kommen, könnte man diese Struktur in eine eigene Methode Refactoring, die sich ändernden Teile als Parameter geben.

Auch InvokeRequired diese if-else-Zweig der Ausgabezeichenfolge verdoppelt hat. Ein wenig Suche hier auf Stackoverflow oder im Internet sollten Sie ein Muster zeigen diese Verdoppelung zu erreichen.

Evernything sonst sieht ganz gut aus.

Es gibt eine Sache, die ich die this.bgwProcessLogin.CancelAsync nicht aufrufen müssen (); wie Sie diese e.Cancel nur einstellen = true;

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top