Pergunta

C # 2008

Eu estou usando o código abaixo para acessar um softphone. No entanto, o progess login é um longo processo, pois há muitas coisas que têm de ser inicializado e controlos a efectuar, eu só colocar um pouco aqui, como seria tornar o código muito tempo para post.

No código abaixo estou verificando se o CancellationPending se o CancelAsync tem sido chamado na minha cancelar evento de clique de botão, antes de fazer cada cheque. Isso é correto? Além disso, se a verificação falhar Eu também chamar a CancelAsync e definir o e.Cancel para true.

Gostaria de saber se meu método que eu usei aqui é o melhor método para uso.

Muito obrigado por qualquer conselho,

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

Solução

Existe talvez apenas um problema: se um da operação em manipulador de eventos DoWork iria durar por um longo tempo. Neste caso, você poderia abortar sua operação pendente só depois é que a operação terminou. Se todas as operações no evento DoWork não pode durar muito tempo (por exemplo, não mais de 5 segundos), está tudo OK, mas se uma das operações podem durar por muito tempo (5 minutos, por exemplo), neste caso do usuário ter esperar até que esta operação terminou.

Se DoWork contém longa operações duradoura que você pode usar algo como AbortableBackgroundWorker. Algo parecido com isto:

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

Neste caso, você pode realmente abortar operações pendentes, mas você também tem algumas restrições (para mais informações sobre abortar thread gerenciado e algumas restrições veja encanamento as profundezas do ThreadAbortException Usando Rotor ).

P.S. Concordo com Oliver que você deve envolver InvokeRequired de forma mais utilizável.

Outras dicas

Você está fazendo isso da maneira certa, eu acredito. Você vai encontrar membros fio que permitem que você cancelar ou abortar um fio, mas você não quiser usá-los para algo como isto. Pode parecer um pouco estranho ter todas as verificações "Cancelado" em seu código, mas que lhe permite controlar exatamente quando sair do seu segmento. Se você fosse "rude" abort o segmento de trabalho, o segmento não tem controle de quando ele sai, e poderia haver estado corrompido.

Dentro de sua função DoWork () que você escreveu .... Dependendo de como muitas tarefas da mesma estrutura estão vindo como o exibido duas uma, você poderia refatorar essa estrutura em um método próprio, dando as partes mutáveis ??como parâmetros.

Além disso, este InvokeRequired if-else ramo dobrou a cadeia de saída. Um pouco de pesquisa aqui no stackoverflow ou na web deve mostrar-lhe um padrão para alcançar este objetivo duplicação.

Evernything olhares outro lugar muito bom.

Há uma coisa que eu não precisa chamar o this.bgwProcessLogin.CancelAsync (); como você pode apenas definir esta e.Cancel = true;

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top