Parar uma linha de execução com tecla Topic is solved

Tire suas dúvidas sobre programação em AutoHotkey

Moderator: Gio

beckfest
Posts: 8
Joined: 11 Dec 2020, 10:00

Parar uma linha de execução com tecla

10 Feb 2021, 03:16

Bom dia, como posso cancelar a execução de uma linha de comando apertando uma tecla? Por exemplo:

Code: Select all

;LINHA 1
{
R::
{
Send a
Sleep 500
Send b
Sleep 500
Send c
Sleep 500
Send d
Sleep 500
Send e
Sleep 500
return
}
}

;LINHA 2
{
T::
{
(COMANDO)
Click, L, 100, 100
return
}
}
Se eu apertar R, como cancelo essa LINHA 1 antes do return executando a LINHA 2 com T (Suponho que o comando deva estar na posição (COMANDO))?
Last edited by gregster on 10 Feb 2021, 03:18, edited 1 time in total.
Reason: Topic moved to 'Ajuda e Suporte Geral'.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Parar uma linha de execução com tecla  Topic is solved

10 Feb 2021, 09:40

Bom dia Beckfest.

A coisa não funciona exatamente desse jeito que você pensou. Infelizmente não existe um comando para cancelar threads interrompidos ou suspensos (underlying threads) no AutoHotkey v1.1+ (somente podemos terminar o thread atual, o que faria a execução voltar ao último thread suspenso, que somente então poderia ser terminado com um comando).

Isso meio que ocorre por causa da característica de o AutoHotkey v1.1+ padrão simular um multithreading (o que no momento exige um controle de buffer dos threads suspensos/interrrompidos, o que por sua vez torna difícil permitir o controle deles pelo script enquanto ainda estão neste estado). Mas você poderia fazer algo desse tipo no AutoHotkey_H (que usa multithreading verdadeiro).

:arrow: Tendo dito isto, nada impede que você solucione essa questão no AutoHotkey v1.1+ usando simplesmente a própria lógica da programação.

Aqui vão alguns exemplos de soluções:

Exemplo 1: Em alguns scripts mais simples este problema também pode ser resolvido usando o comando Reload, que basicamente reinicia o script ao invés de voltar a execução para a rotina anterior.

Code: Select all

;LINHA 1
R::
Send a
Sleep 500
Send b
Sleep 500
Send c
Sleep 500
Send d
Sleep 500
Send e
Sleep 500
return

;LINHA 2
T::
Send f
Sleep 500
Send g
Sleep 500
Send h
Sleep 500
Send i
Sleep 500
Send j
Sleep 500
Reload ; O comando reload reinicia o script, portanto, a execução NÃO volta para a rotina LINHA 1.
return

Exemplo 2: Mas em alguns scripts mais complexos, onde o reload não seria adequado por outras razões, você também pode usar uma variável de checagem, de modo que uma rotina só envie o próximo comando se outra rotina não tiver interrompido ela durante a sua execução.

Code: Select all

Thread, Interrupt, 0 ; Começamos definindo que qualquer thread possa ser interrompido imediatamente.

;LINHA 1
R::
WAS_INTERRUPTED := 0 ; Depois, neste thread, definimos uma variável de checagem com valor inicial 0.
If (WAS_INTERRUPTED = 0) ; E checamos o valor dela antes de quaisquer ações.
{
	Send a
	Sleep 500
}
If (WAS_INTERRUPTED = 0)
{
	Send b
	Sleep 500
}
If (WAS_INTERRUPTED = 0)
{
	Send c
	Sleep 500
}
If (WAS_INTERRUPTED = 0)
{
	Send d
	Sleep 500
}
If (WAS_INTERRUPTED = 0)
{
	Send e
	Sleep 500
}
return

;LINHA 2
T::
WAS_INTERRUPTED := 1 ; Nesta hotkey, definimos que o valor da variável será 1. Isso sginifica que se essa hotkey for chamada enquanto a outra está em execução, mesmo que a ordem de execução volte pra rotina anterior ao final desta, o valor da variável de checagem aqui redefinido fará com que os comandos da outra rotina não sejam enviados.
Send f
Sleep 500
Send g
Sleep 500
Send h
Sleep 500
Send i
Sleep 500
Send j
Sleep 500
return

:arrow: A quantidade de checagens (Ifs) consultando a variável de checagem não precisa ser a cada linha, pode ser a cada X linhas, você definirá qual o grau de imediatismo necessário a essa interrupção.


Exemplo 3: Também é possível resolver a questão usando um controle mais adequado dos threads em execução, de modo que ao invés de voltar ao thread anterior, o script pule para um novo thread (um de pausa contínua, para que não faça nada) sempre que terminar um thread atual. Essa solução parece ser a mais cômoda para muitos casos.

Code: Select all

Thread, Interrupt, 0 ; Começamos definindo que qualquer thread possa ser imediatamente interrompido. 
#MaxThreadsPerHotkey, 255 ; Depois, definimos que uma hotkey possa chamar até 255 threads (o número máximo)
#MaxThreads, 255 ; E também que o script possa ter até 255 threads simultâneos (suspensos ou não) (o número máximo)
Threads_Totais := 0 ; E faremos uma contagem desses threads.

;LINHA 1
R::
Threads_Totais++ ; Sempre que chamamos uma hotkey, contamos ela como um thread novo.
If (Threads_Totais >= 254) ; E se chegarmos a mais que 254 threads...
{
	Reload ; Reiniciamos o script. Mas isso será feito somente se realmente precisarmos chamar as hotkeys mais de 254 vezes em uma execução só...
}
Send a
Sleep 500
Send b
Sleep 500
Send c
Sleep 500
Send d
Sleep 500
Send e
Sleep 500
Goto, EM_PAUSA ; E quanto toda hotkey terminar, ela iniciará uma rotina de pausa sem fim (para que não volte a uma hotkey anterior).

;LINHA 2
T::
Threads_Totais++
If (Threads_Totais > 254)
{
	Reload
}
Send f
Sleep 500
Send g
Sleep 500
Send h
Sleep 500
Send i
Sleep 500
Send j
Sleep 500
Goto, EM_PAUSA


EM_PAUSA:
Threads_Totais++ ; As rotinas de pausas também contam como threads.
Loop 
{
	Sleep 20
}
Return

:arrow: E lembrando: Uma solução final seria usar o AutoHotkey_H, que possui a funcionalidade de multithreading verdadeiro, permitindo que você termine qualquer thread na hora que quiser.


Espero ter ajudado, se ainda tiver alguma dúvida, basta postar abaixo :thumbup:
beckfest
Posts: 8
Joined: 11 Dec 2020, 10:00

Re: Parar uma linha de execução com tecla

10 Feb 2021, 11:38

@Gio Bom dia, o exemplo 2 me serviu perfeitamente, um pouco trabalhoso, mas funcional, obrigado :thumbup:

Return to “Ajuda e Suporte Geral”

Who is online

Users browsing this forum: No registered users and 37 guests