Pergunta

Eu estou trabalhando em um aplicativo WinForms e eu tenho um controle de usuário nele. Os botões nos eventos controle do usuário levantar até o formulário a ser tratado por outro código. Um dos botões começa alguns processses que irá causar problemas se eles correm simultaneamente. Tenho lógica no código para gerenciar o estado tão tipicamente um usuário não pode executar o processo se ele já está em execução. No entanto, se o usuário clica duas vezes no botão que irá iniciar o processo duas vezes tão rapidamente que é difícil para mim para impedi-lo.

Eu estou querendo saber, qual é a melhor maneira de lidar com isso?

Eu comecei desativando o botão no evento de clique, mas o segundo clique vem antes do primeiro clique faz com que o botão seja desativado. Definir outras bandeiras no código não pegá-lo também.

Eu estou considerando a adição de algum tipo de bloqueio de sincronização no código que gera o evento, mas eu estou querendo saber se algum de vocês tem uma idéia melhor.

Uma vez que este projecto é principalmente completar Estou procurando respostas que não envolvem uma reescrita radical do aplicativo (como implementar o bloco de aplicativo composto), no entanto, sinta-se livre para postar essas idéias muito desde que eu posso usá-los em meus próximos projetos.

Foi útil?

Solução

Certifique-se de que o botão incapacitante ou qualquer outro bloqueio que você faz é a / primeira / coisa que você faz no seu manipulador de eventos. Eu ficaria extremamente surpreso se você poderia fila dois eventos de clique antes mesmo dos primeiros fogos de instrução, mas suponho que isso é possível se você estiver em um computador muito lento desse esbarrado com outros aplicativos.

Nesse caso, use uma bandeira.

private bool runningExclusiveProcess = false;

public void onClickHandler(object sender, EventArgs e)
{
    if (!runningExclusiveProcess)
    {
        runningExclusiveProcess = true;
        myButton.Enabled = false;

        // Do super secret stuff here

        // If your task is synchronous, then undo your flag here:
        runningExclusiveProcess = false;
        myButton.Enabled = true;
    }
}

// Otherwise, if your task is asynchronous with a callback, then undo your flag here:
public void taskCompletedCallback()
{
    runningExclusiveProcess = false;
    myButton.Enabled = true;
}

Se você ainda pode obter em dois cliques fora de algo como isso, então certifique-se você não está inscrito acidentalmente a um evento doubleClick, ou qualquer outra coisa wonky está acontecendo.

Outras dicas

Você está manipulando o evento duas vezes?

Estou muito surpreso ao ler que o segundo clique está chegando antes que você pode desativar o botão. Gostaria de olhar para se certificar de que você não está ligando o evento duas vezes. Eu tenho feito isso por acidente antes. Você vai então receber dois eventos, quase instantaneamente.

A bandeira desativar no botão que não iria ser definido até que os concluída manipulador de eventos botão e todos os cliques adicionais serão enfileiradas na fila de janelas mensagem por trás do primeiro clique. Certifique-se o manipulador de eventos botão completa rapidamente para liberar o segmento. Existem várias maneiras de fazer isso, mas todos envolvem eather gerando um fio ou manter um segmento de trabalho pronto e esperando por uma AutoResetEvent.

Por acaso, você está rotulando o botão com um ícone? Por todos os meios usar o código para evitar a execução de dois processos ao mesmo tempo, mas você pode reduzir um duplo clique sobre o lado humano se a sua aparência de botão e age como um botão de comando convencional (retangular, etiqueta apenas texto, "levantou" superfície que deprime em um clique). Apenas um pensamento.

Desativar o botão assim que ele é clicado. Assim, o evento não pode ser tratada duas vezes. Assim que o evento havia sido tratado, você pode reativar o botão.

A resposta verificada está perto, se anedótica na melhor das hipóteses. Para o uninitated que está faltando muito código para fazer sentido. Eu escrevi um artigo sobre o uso de temporizadores e Threads eo exemplo de código é realmente fácil de entender. Tente ler através dele e ver se você pode definir os sinalizadores a partir do exemplo acima, executando o seu processo de tarefa em uma nova linha:

http://www.robault.com/category/Threading.aspx

Desativar o botão após o primeiro usuário clica nele e antes de iniciar a tarefa. Quando concluída tarefas, re-ativar o botão.

Eu comecei desativando o botão no evento de clique, mas o segundo clique vem antes do primeiro clique faz com que o botão para ser desativado. Definir outras bandeiras no código não pegá-lo também.

WinForms dada é inerentemente single-threaded, não deve ser possível para o segundo clique ao fogo antes do processamento para a primeira foi concluída (a menos que você estiver usando novos tópicos ou BackgroundWorkers etc).

Você pode nos mostrar um exemplo que ilustra o seu problema?

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