Лучший способ справиться с двойным нажатием кнопок в приложении winforms?

StackOverflow https://stackoverflow.com/questions/255104

Вопрос

Я работаю над приложением WinForms и в нем есть пользовательский элемент управления. Кнопки в пользовательском элементе управления вызывают события до формы, которая будет обрабатываться другим кодом. Одна из кнопок запускает некоторые процессы, которые могут вызвать проблемы, если они запускаются одновременно. У меня есть логика в коде для управления состоянием, поэтому обычно пользователь не может запустить процесс, если он уже запущен. Однако, если пользователь дважды щелкнет кнопку, он запустит процесс дважды так быстро, что мне будет сложно его предотвратить.

Мне интересно, как лучше всего с этим справиться?

Я начал с отключения кнопки в событии щелчка, но второй щелчок происходит до того, как первый щелчок вызывает отключение кнопки. Установка других флагов в коде тоже не уловила.

Я подумываю добавить какую-нибудь синхронизирующую блокировку в код, который вызывает событие, но мне интересно, есть ли у кого-нибудь из вас идея получше.

Поскольку этот проект в основном завершен, я ищу ответы, которые не требуют радикальной переписывания приложения (например, реализации составного блока приложения), однако не стесняйтесь публиковать и эти идеи, поскольку я могу использовать их в мои следующие проекты.

Это было полезно?

Решение

Убедитесь, что отключение вашей кнопки или любая другая блокировка, которую вы делаете, - это / first / вещь, которую вы делаете в обработчике событий. Я был бы очень удивлен, если бы вы могли поставить в очередь два события щелчка еще до того, как сработает первая инструкция, но я полагаю, что это возможно, если вы работаете на очень медленном компьютере, перегруженном другими приложениями.

В этом случае используйте флаг.

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

Если вы все еще можете получить в два клика что-то подобное, убедитесь, что вы случайно не подписаны на событие doubleClick или что-то еще происходит не так.

Другие советы

Вы обрабатываете событие дважды?

Я очень удивлен, узнав, что второй щелчок поступает до того, как вы сможете отключить кнопку. Я хотел бы убедиться, что вы не подключаете событие дважды. Я сделал это случайно раньше. Затем вы получите два события, почти мгновенно.

Флаг отключения для этой кнопки не будет установлен до тех пор, пока не будет завершен обработчик события кнопки, и любые дополнительные щелчки будут поставлены в очередь в очереди сообщений Windows после первого щелчка. Убедитесь, что обработчик события кнопки завершается быстро, чтобы освободить поток пользовательского интерфейса. Есть несколько способов сделать это, но все они включают в себя создание потока или сохранение готовности рабочего потока и ожидание AutoResetEvent.

Вы случайно не помечаете кнопку значком? Безусловно, используйте код, чтобы предотвратить запуск двух процессов одновременно, но вы можете уменьшить двойной щелчок на стороне пользователя, если ваша кнопка выглядит и действует как обычная командная кнопка (прямоугольная, только текстовая метка, «поднятая» поверхность, которая нажимает на щелчок). Просто мысль.

Отключите кнопку, как только она будет нажата. Таким образом, событие не может быть обработано дважды. Как только событие было обработано, вы можете снова включить кнопку.

Проверенный ответ близок, если в лучшем случае анекдотичный. Для непосвященных отсутствует слишком много кода, чтобы иметь смысл. Я написал статью об использовании таймеров и потоков, и пример кода ДЕЙСТВИТЕЛЬНО прост для понимания. Попробуйте прочитать его и посмотреть, сможете ли вы установить флаги из приведенного выше примера, запустив процесс задачи в новом потоке:

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

Отключите кнопку после того, как пользователь впервые щелкнет ее и перед запуском задачи. После завершения задачи снова включите кнопку.

  

Я начал с отключения кнопки   в событии щелчка, но второй   клик приходит до первого клика   вызывает отключение кнопки.   Установка других флагов в коде не   поймать это тоже.

Поскольку WinForms по своей природе однопоточные, второй клик не должен срабатывать до завершения обработки первого клика (если вы не используете новые потоки или BackgroundWorkers и т. д.).

Можете ли вы показать нам пример, иллюстрирующий вашу проблему?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top