Pregunta

C # 2008

Estoy utilizando el siguiente código para iniciar sesión en un softphone. Sin embargo, el proceso de inicio de sesión es un proceso largo, ya que hay muchas cosas que deben inicializarse y verificaciones que se deben realizar, solo he puesto algunas aquí, ya que el código sería demasiado largo para publicar.

En el código que aparece a continuación, estoy verificando si Cancelación está pendiente si se ha llamado a CancelAsync en el evento de clic del botón Cancelar, antes de realizar cada comprobación. ¿Es esto correcto? Además, si la comprobación falla, también llamo a CancelAsync y configuro e.Cancel en verdadero.

Me gustaría saber si mi método que he usado aquí es el mejor método para usar.

Muchas gracias por cualquier consejo,

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";
}
¿Fue útil?

Solución

Puede que haya un solo problema: si una de las operaciones en el controlador de eventos DoWork duraría mucho tiempo. En este caso, podría cancelar su operación pendiente SOLAMENTE después de que esa operación haya finalizado. Si todas las operaciones en el evento DoWork no pueden durar mucho tiempo (por ejemplo, no más de 5 segundos), todo está bien, pero si una de las operaciones puede durar mucho tiempo (5 minutos, por ejemplo) en este caso, el usuario tiene Esperar hasta que termine esta operación.

Si DoWork contiene operaciones de larga duración, puede usar algo como AbortableBackgroundWorker. Algo como esto:

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

En este caso, realmente puede abortar las operaciones pendientes, pero también tiene algunas restricciones (para obtener más información sobre el aborto de subprocesos gestionados y algunas restricciones, consulte Fontanería de las profundidades de la excepción ThreadAbortException utilizando Rotor ).

P.S. Estoy de acuerdo con Oliver en que deberías envolver InvokeRequired en una forma más utilizable.

Otros consejos

Lo estás haciendo de la manera correcta, creo. Encontrarás miembros del hilo que te permiten terminar o abortar un hilo, pero no quieres usarlos para algo como esto. Puede parecer un poco extraño que se haya cancelado " " " comprueba su código, pero eso le permite controlar exactamente cuándo sale de su hilo. Si fueras " groseramente " abortar el subproceso de trabajo, el subproceso no tiene control de cuándo sale y podría haber estado dañado.

Dentro de su función DoWork (), escribió ... . Dependiendo de cuántas tareas de la misma estructura se presenten como las dos mostradas, puede refactorizar esta estructura en un método propio, dando a las partes cambiantes como parámetros.

También esta rama InvokeRequired if-else ha duplicado la cadena de salida. Una pequeña búsqueda aquí en stackoverflow o en la web debería mostrarle un patrón para lograr esta duplicación.

Todo lo demás se ve bastante bien.

Hay una cosa que no necesito llamar a this.bgwProcessLogin.CancelAsync (); como puede configurar esto e.Cancel = true;

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top