AO LIBERAR FORM, A ROTINA CONTINUA...

MARLON 31/08/2007 10:16:54
#233546
Bom dia amigos.
Quando fecho um formulário, através de "Unload Me", no momento em que uma rotina está ainda dentro de um laço de repetição, o formulário é, aparentemente, descarregado, mas a rotina ainda continua executando, em segundo plano.
Como descobri: A cada iteração desse laço, são feitas algumas consultas e outras execuções em banco, o que sempre deu um "delay" perceptível (apesar de todos os 'DoEvents'), então, mesmo depois que fecho o formulário, sente-se o velho delay, tipicamente pulsando em cada iteração...
Então, estou fechando o formulário de forma errada? Há uma maneira mais otimizada de fechar, que garanta o encerramento de todas as rotinas que estejam em execução?

Obrigado!
CLEVERTON 31/08/2007 12:16:23
#233585
isso é comportamento normal de uma rotina...

agora se vc quer abandonar o laço vc faz uma verificar e usa o comando exit for e depois exit sub para interromper.
MJAC 31/08/2007 12:32:14
#233591
Resposta escolhida
Na verdade tem dois problemas ai.

Primeiro usar DoEvents e rotinas longas é suicídio, pois essa rotina come muito processamento da máquina e acaba demorando umas 10 vezes mais tempo pra terminar. Use a api GetInputState() para detectar o pedido de processamento e ai sim use DoEvents para fornece a permissão só quando pedido.

Outra coisa para cancelar o laço não é só fechar o form não. é preciso sair da rotina, então criamos uma variavel booleana para informar que um pedido de cancelamento ocorreu e então "Exit Do" ou "Exit For" dependo do tipo de laço que você criou.

Exemplo para teste, desenhe dois label e dois command no form. E na área de código cole isso:

  
Private Declare Function GetInputState Lib "user32" () As Long
Private vCancelar As Boolean 'Essa é a variável de cancelamento

Private Sub Command1_Click()
Dim lngCounter As Long, Inic As Date
vCancelar = False
Me.MousePointer = vbHourglass

Inic = Time
' Qualquer loop longo que possa precisar ser interrompido.
For lngCounter = 0 To 10000000
If lngCounter Mod 100 Then
' Entra aqui somente de 100 em 100 iterações.
If GetInputState() <> 0& Then
' Um evento do mouse ou keyboard está na fila de
' mensagens, então, chamamos o DoEvents para que
' a mensagem seja processada.
DoEvents
If vCancelar Then
' O usuário cancelou o processo.
Exit For
End If
End If
End If
Next lngCounter
Label1.Caption = DateDiff("s", Inic, Time)

Inic = Time
' Qualquer loop longo que possa precisar ser interrompido.
For lngCounter = 0 To 10000000
If lngCounter Mod 100 Then
' Entra aqui somente de 100 em 100 iterações.
DoEvents
If vCancelar Then
' O usuário cancelou o processo.
Exit For
End If
End If
Next lngCounter
Label2.Caption = DateDiff("s", Inic, Time)

Me.MousePointer = vbDefault
End Sub

Private Sub Command2_Click()
' O usuário cancelou o processo.
vCancelar = True
End Sub


Tenta ai, abraços...
MARLON 31/08/2007 13:58:21
#233615
Valeu MJ,
Realmente nunca tinha parado pra pensar no DoEvents dessa forma, pois tempo de processamento por aqui é absolutamente irrisório em relação ao tempo gasto com consultas de banco (em tabelas com milhões de registros). Tenho despendido mais tempo otimizando a modelagem, métodos de acesso e instruções SQL.

Abraços!
Tópico encerrado , respostas não são mais permitidas