Отмена длительного процесса в VB6.0 без DoEvents?

Можно ли отказаться от долгого процесса в VB6.0 без использования DoEvents?

Например:

for i = 1 to someVeryHighNumber ' Do some work here ' ... if cancel then exit for end if next Sub btnCancel_Click() cancel = true End Sub 

Я предполагаю, что мне нужно «DoEvents» до «if cancel then …», есть ли лучший способ? Прошло много времени…

Нет, вы поняли это правильно, вы определенно хотите DoEvents в своем цикле.

Если вы помещаете DoEvents в свой основной цикл и обнаруживаете, что слишком GetQueueStatus обрабатываете обработку, попробуйте вызвать функцию GetQueueStatus (которая намного быстрее, чем DoEvents) Windows API, чтобы быстро определить, нужно ли даже звонить в DoEvents. GetQueueStatus сообщает вам, есть ли какие-либо события для обработки.

 ' at the top: Declare Function GetQueueStatus Lib "user32" (ByVal qsFlags As Long) As Long ' then call this instead of DoEvents: Sub DoEventsIfNecessary() If GetQueueStatus(255) <> 0 Then DoEvents End Sub 

Нет, вы должны использовать DoEvents, иначе все события пользовательского интерфейса, клавиатуры и таймера будут оставаться в очереди.

Единственное, что вы можете сделать, это вызвать DoEvents один раз на каждые 1000 итераций или таких.

Является ли цикл «for» запущенным в streamе графического интерфейса? Если да, то вам понадобится DoEvents. Вы можете использовать отдельный stream, и в этом случае DoEvents не требуется. Вы можете сделать это в VB6 (не просто).

Вы можете запустить его на отдельном streamе, но в VB6 это королевская боль. DoEvents должны работать. Это взломать, но тогда и VB6 (10-летний ветеран VB говорит здесь, поэтому не меняйте меня).

Разделите задачу на длительную работу на кванты. Такие задачи часто управляются простым циклом, поэтому разрезайте его на 10, 100, 1000 и т. Д. Итераций. Используйте элемент управления таймером, и каждый раз, когда он срабатывает, выполняет часть задачи и сохраняет свое состояние во время движения. Для начала настройте начальное состояние и включите таймер. По завершении отключите таймер и обработайте результаты.

Вы можете «настроить» это, изменив количество работы на квант. В обработчике событий Timer вы можете проверить «отменить» и остановиться по мере необходимости. Вы можете сделать все это аккуратно, объединив рабочую нагрузку и таймер в UserControl с событием Completed.

Это хорошо работает для меня, когда мне это нужно. Он проверяет, нажал ли пользователь клавишу эвакуации, чтобы выйти из цикла.

Обратите внимание, что у него действительно большой недостаток: он обнаружит, что пользователь ударил ключ escape в ЛЮБОЙ программе – а не только ваш. Но это отличный трюк в разработке, когда вы хотите дать себе возможность прервать длинный цикл работы или способ удерживать клавишу shift для обхода части кода.

 Option Explicit Private Declare Function GetAsyncKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer Private Sub Command1_Click() Do Label1.Caption = Now() Label1.Refresh If WasKeyPressed(vbKeyEscape) Then Exit Do Loop Label1.Caption = "Exited loop successfully" End Sub Function WasKeyPressed(ByVal plVirtualKey As Long) As Boolean If (GetAsyncKeyState(plVirtualKey) And &H8000) Then WasKeyPressed = True End Function 

Документация для GetAsyncKeyState находится здесь:

http://msdn.microsoft.com/en-us/library/ms646301(VS.85).aspx

EDIT получается, что статья MSDN ошибочна, и техника НЕ РАБОТАЕТ 🙁

Вот статья об использовании компонента .NET BackgroundWorker для запуска задачи в другом streamе из VB6.

Вот довольно стандартная схема асинхронной фоновой обработки в VB6. (Например, это в книге Дэна Эпплмана и в образцах Microsoft VB6.) Вы создаете отдельный ActiveX EXE для выполнения работы: таким образом, работа выполняется автоматически в другом streamе в отдельном процессе (что означает, что вам не нужно беспокоиться о перетаскиваемые переменные).

  • Объект VB6 ActiveX EXE должен выставить событие CheckQuitDoStuff (). Это берет ByRef Boolean, называемый Quit.
  • Клиент вызывает StartDoStuff в объекте ActiveX EXE. Эта процедура запускает таймер по скрытой форме и немедленно возвращается . Это разблокирует вызывающий stream. Интервал таймера очень короткий, поэтому событие Timer срабатывает быстро.
  • Обработчик событий Timer отключает таймер, а затем снова возвращается к методу DoStuff объекта ActiveX. Это начинает длительную обработку.
  • Периодически метод DoStuff вызывает событие CheckQuitDoStuff. Обработчик события клиента проверяет специальный флаг и устанавливает Quit True, если это необходимо для прерывания. Затем DoStuff прерывает вычисление и возвращает раньше, если Quit is True.

Эта схема означает, что клиент фактически не должен быть многопоточным, так как вызывающий stream не блокируется, пока происходит «DoStuff». Трудная часть заключается в том, чтобы DoStuff поднимал события через соответствующие промежутки времени – слишком долго, и вы не можете уйти, когда захотите: слишком короткий, и вы замедляете DoStuff без необходимости. Кроме того, когда DoStuff завершает работу, он должен выгрузить скрытую форму.

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

  • Как зарегистрировать COM-библиотеку, написанную на C #, с помощью Regsvr32?
  • Перерыв в модуле classа или разрыв по необработанным ошибкам (ошибка проверки ошибок VB6, настройка параметров в среде IDE)
  • Назначение объектов в VB6
  • Использование двоеточий для размещения двух операторов в одной строке в Visual Basic
  • Функция IsDate возвращает неожиданные результаты
  • Обучение VB6
  • Сравнение инструментов сравнения для визуального базового 6.0
  • Использовать stream в программировании в vb6
  • Каков наилучший способ использования веб-сервиса из VB6?
  • Как изменить расширенные свойства файла с помощью vba
  • Кто-нибудь имел успех с Visual Studio 6 в Windows 7?
  • Interesting Posts

    Как повторно использовать JSON / JAXB от Джерси для сериализации?

    Как получить данные из отдельных листов, отображаемых в отдельной отдельной рабочей таблице

    Utf8 hebrew на консоли mysql на debian (через шпатлёвку на окнах)

    Показать текущее местоположение внутри fragmentа карты Google

    Можем ли мы использовать JSch для обмена данными на основе SSH?

    Почему вызовы метода интерфейса медленнее, чем конкретные вызовы?

    Создание загрузочного флеш-диска для установки windows 7 из Fedora

    Поддержка RAID материнской платы или аппаратный RAID-контроллер?

    Есть ли разница между кабелями «Thunderbolt» и «Mini DisplayPort»?

    ОШИБКА: ошибка API Карт Google: MissingKeyMapError

    Найти элементы в одном столбце, которые не находятся в другом столбце

    Почему 700 МБ пустых дисков подходят только тем, что говорит iTunes, составляет около 150 МБ песен?

    Как проверить, установлено ли определенное обновление безопасности Windows?

    Программируемая версия подмножества – для оценки ее состояния при вызове из другой функции

    R return corrplot как объект

    Давайте будем гением компьютера.