sirve que para vb6

que - ¿Cancela un proceso de larga ejecución en VB6.0 sin DoEvents?



doevents access (8)

¿Es posible cancelar un proceso largo en VB6.0 sin utilizar DoEvents?

Por ejemplo:

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

Supongo que necesito un "DoEvents" antes del "si cancelas, entonces ..." ¿hay una mejor manera? Ha sido un tiempo...


No, debe usar DoEvents, de lo contrario, todos los eventos de UI, teclado y temporizador permanecerán en espera en la cola.

Lo único que puede hacer es llamar a DoEvents una vez por cada 1000 iteraciones o similares.


Puedes comenzar en un hilo separado, pero en VB6 es un dolor real. DoEvents debería funcionar. Es un truco, pero también lo es VB6 (veterano de VB de 10 años hablando aquí, así que no me modifiques).


¿Se está ejecutando el bucle "for" en el hilo de la GUI? Si es así, sí, necesitarás un DoEvents. Es posible que desee utilizar un subproceso separado, en cuyo caso un DoEvents no sería necesario. Puedes hacer esto en VB6 (no simple).


Divida la tarea larga en quanta. Tales tareas a menudo son impulsadas por un simple bucle, así que córtalo en iteraciones de 10, 100, 1000, etc. Use un control de temporizador y cada vez que dispare haga parte de la tarea y guarde su estado sobre la marcha. Para comenzar, configure el estado inicial y active el temporizador. Cuando termine, desactive el temporizador y procese los resultados.

Puedes "ajustar" esto cambiando la cantidad de trabajo que se realiza por quantum. En el controlador de eventos Timer, puede verificar la "cancelación" y detenerse antes de lo necesario. Puede hacerlo todo más ordenado agrupando la carga de trabajo y el temporizador en un control de usuario con un evento completado.


No, lo hiciste bien, definitivamente quieres DoEvents en tu loop.

Si coloca los DoEvents en su bucle principal y descubre que ralentiza demasiado el procesamiento, intente llamar a la función API de Windows GetQueueStatus (que es mucho más rápido que DoEvents) para determinar rápidamente si es necesario llamar a DoEvents. GetQueueStatus le informa si hay algún evento para procesar.

'' 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


Esto funciona bien para mí cuando lo necesito. Verifica si el usuario ha presionado la tecla de escape para salir del ciclo.

Tenga en cuenta que tiene un gran inconveniente: detectará si el usuario pulsa la tecla Escape en CUALQUIER aplicación, no solo la suya. Pero es un gran truco en el desarrollo cuando quieres darte una forma de interrumpir un bucle de ejecución larga, o una forma de mantener presionada la tecla Mayús para eludir un poco de código.

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

La documentación para GetAsyncKeyState está aquí:

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


Aquí hay un esquema bastante estándar para el procesamiento de fondo asincrónico en VB6. (Por ejemplo, está en el libro de Dan Appleman y en las muestras VB6 de Microsoft). Usted crea un EXE ActiveX separado para hacer el trabajo: de esa manera el trabajo se realiza automáticamente en otro hilo, en un proceso separado (lo que significa que no tiene que preocuparse variables pisoteadas).

  • El objeto EXE VB6 ActiveX debe exponer un evento CheckQuitDoStuff (). Esto toma un booleano ByRef llamado Salir.
  • El cliente llama a StartDoStuff en el objeto EXE de ActiveX. Esta rutina inicia un temporizador en una forma oculta e inmediatamente regresa . Esto desbloquea el hilo de llamada. El intervalo del temporizador es muy corto, por lo que el evento del temporizador se dispara rápidamente.
  • El controlador de eventos Timer desactiva el temporizador y vuelve a llamar al método DoStuff del objeto ActiveX. Esto comienza el procesamiento largo.
  • Periódicamente, el método DoStuff plantea el evento CheckQuitDoStuff. El controlador de eventos del cliente verifica la bandera especial y establece Salir verdadero si es necesario abortar. Entonces DoStuff aborta el cálculo y regresa temprano si Quit es verdadero.

Este esquema significa que el cliente no necesita ser multihilo, ya que el hilo de llamada no se bloquea mientras está ocurriendo "DoStuff". La parte difícil es asegurarse de que DoStuff plantea los eventos a intervalos apropiados, demasiado tiempo, y no se puede abandonar cuando se quiere: demasiado corto, y se está desacelerando DoStuff innecesariamente. Además, cuando DoStuff se cierra, debe descargar el formulario oculto.

Si DoStuff realmente logra hacer todo esto antes de ser cancelado, puede plantear un evento diferente para decirle al cliente que el trabajo ha finalizado.