Лучший способ справиться с двойным нажатием кнопок в приложении winforms - PullRequest
4 голосов
/ 01 ноября 2008

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

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

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

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

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

Ответы [ 8 ]

5 голосов
/ 01 ноября 2008

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

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

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, или что-то еще происходит.

3 голосов
/ 01 ноября 2008

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

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

1 голос
/ 01 ноября 2008

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

0 голосов
/ 29 июня 2009

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

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

0 голосов
/ 04 ноября 2008

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

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

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

0 голосов
/ 04 ноября 2008

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

0 голосов
/ 03 ноября 2008

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

0 голосов
/ 01 ноября 2008

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

...