Página 1 de 1

Usando multithread

Enviado: 26 Fev 2025 13:19
por JoséQuintas
Usar multithread é simples, ao mesmo tempo que pode se tornar complexo.

Multithread é igual EXE separado, mas a thread principal é quem manda.
Fechou a thread principal fecha tudo ou, no mínimo, acaba com muitas variáveis.

Supondo que seu aplicativo tem a procedure Main, que é o início do aplicativo.
Altere o nome pra Main2, e crie outra Main.

Código: Selecionar todos

PROCEDURE Main

   hb_ThreadStart( { || Main2() } )
   hb_ThreadWaitForAll()

   RETURN

PROCEDURE HB_GTSYS

   REQUEST HB_GT_WVG_DEFAULT

   RETURN
Esta vai ser uma Main() invisível, esperando tudo acabar.
Seu aplicativo vai rodar na segunda thread.
Fechou o aplicativo, esta thread também fecha.

Seu aplicativo, se usar GTWVG, vai abrir uma outra janela GTWVG pra trabalhar.
Se for fivewin vai abrir dialog fivewin, se for hwgui vai abrir dialog hwgui, se for minigui vai dar erro porque minigui não está preparada pra isso.
Ou... vai abrir o que você quiser, você decide.
nota: minigui tem jeito de funcionar.

Usando multithread

Enviado: 26 Fev 2025 13:27
por JoséQuintas
O que uso aqui é hb_gtReload( "WVG" )

Isso cria um segundo ambiente de trabalho, com tela e teclado.
Mas a tela não aparece automático, só vai aparecer se você usar @ SAY, CLS, Inkey()

Código: Selecionar todos

PROCEDURE Modulo

   hb_gtReload( "WVG" )
   SetMode(33,100)
   CLS
   ? "Tecle algo"
   Inkey()

   RETURN
Está aí um módulo multithread.
A única diferença é o hb_gtReload("WVG") que vai carregar uma tela nova.
Se preferir: UMA DIALOG NOMODAL, uma dialog que não vai bloquear a anterior.

Basicamente é isso.
Temos uma rotina Main() invisível, e temos o módulo com sua própria janela.
Fechou o módulo, a Main() fecha.
Pode chamar o módulo quantas vezes quiser, vai abrir tantas janelas quanto chamar.

Aqui uso módulos GTWVG, HWGUI ou FIVEWIN.

O que tem de extraordinário nisso ? nada.

Usando multithread

Enviado: 26 Fev 2025 13:44
por JoséQuintas
Variáveis e arquivos

É aqui que a coisa fica interessante, pode facilitar ou complicar.

Arquivos são independentes por thread.
Pode usar isto em cada thread, uma não mexe com a outra

Código: Selecionar todos

USE clientes
...
CLOSE DATABASES
Variáveis PUBLIC e PRIVATE não são visíveis entre threads - este é o default, é o que eu uso, prefiro assim.

Mas quero controlar usuário que entrou no aplicativo, ou empresa em uso.

Aqui crio uma função pra cada, no lugar da variável pública.

Código: Selecionar todos

STATIC AppUserName( x )
   STATIC cAppUserName := ""
   IF x != Nil
      cAppUserName := x
   ENDIF
   RETURN cAppUserName
Nos módulos basta eu usar AppUserName()
E pra setar o inicial AppUserName( nomeusuario )

Resolvido o problema de variável pública.

Poderia ser array, poderia ser classe, poderia ser hash....
Sim poderia, mas desse jeito o compilador dá erro se colocar nome errado.

Pronto, resolvida a questão de variáveis que precisam ser visíveis.

Tem também a variável THREAD STATIC
É o mesmo que a STATIC mas cada thread tem a sua.

Por exemplo, num uso relativamente comum, criar um array com save screen.
Vai salvando na ida, e restaurando na volta.

Em multithread, cada thread tem sua sequência de save/restore screen, uma não pode interferir na outra.
Lembram: multithread é igual EXE separado. Vai salvar tela num EXE e restaurar no outro ? não dá certo.
Declarando esse array como THREAD STATIC , cada EXE/thread vai conter sua lista de save/restore screen, um EXE/thread não mexe com o outro.

Pronto, resolvida a questão de cada thread ter suas próprias variáveis especiais.

No resto, tanto faz, vai poder usar variável PUBLIC, PRIVATE, LOCAL, do jeito de sempre.

Usando multithread

Enviado: 26 Fev 2025 13:56
por JoséQuintas
De um modo geral é isso.

A questão de variáveis é importante.
É isso que pode impedir de usar LIB gráfica, não enxergar variáveis.

minigui costuma usar a variável pública _HMG_SYSDATA
Como é variável pública, não vai estar visível em outras threads.
Vai ser normal dar erro de não encontrar essa variável, se não for thread principal.
Isso tem solução ? sim. Pra cada situação, uma solução.
Resolver um problema não significa que resolveu todos.

Como a rotina de erros da minigui depende dessa variável, ao rodar em multithread você fica até sem mensagem de erro,
São situações a contornar.

É problema de multithread ? não
É problema da minigui ? não exatamente, ninguém usa em multithread, vai dizer que o que ninguém usa dá erro ? Se começarem a usar, aí ajustam a rotina de erro.

Tem também lib com INIT PROCEDURE e INIT FUNCTION.
Isso é executado ao carregar o aplicativo, mas somente uma vez, somente na thread principal.
Pode fazer falta pras outras threads.

Então, multithread é relativamente simples.
Mas nem toda lib é preparada pra isso.
O programador vai ter que entender isso, e fazer o que der.

Misturar LIBs é fácil ?
Teoricamente sim.
Na prática depende de não ter função repetida, com mesmo nome, mas fazendo coisa diferente.
Isso até sem multithread é problema.

Usando multithread

Enviado: 26 Fev 2025 14:00
por JoséQuintas
Problema conhecido em HWGUI.

HWGUI tem DIALOG e WINDOW.
Fazem praticamente a mesma coisa.
Mas WINDOW dá erro em multithread, esquisito.
Só não usar.

Usando multithread

Enviado: 26 Fev 2025 14:03
por JoséQuintas
Problema conhecido em FIVEWIN.

FIVEWIN mexe com a janela em uso.
Muda palette de cores, linhas/colunas, etc.
Só colocar hb_gtReload("WVG"), e dar uma janela invisível pro fivewin fazer suas mudanças.
Isso se houver janela GTWVG em uso antes da chamada do fivewin.

Usando multithread

Enviado: 26 Fev 2025 14:20
por JoséQuintas
Em GUI, quando dá erro, GUI fecha tudo que está em aberto.
Em multithread pode não fechar.
Vai ser normal ver janela ZUMBI.

Uma coisa é programa ZUMBI: não tem tela, tem que fechar no gerenciador de tarefas

Outra coisa é janela ZUMBI: a janela não foi destruída mas ficou sem programa, também tem que fechar no gerenciador de tarefas.
Aqui alterei a errorsys com uma chamada a uma função do fivewin: PostQuitMessage(0).
Isso fecha a thread, e destrói tudo que ela criou, não existe mais janela ZUMBI.

Essas coisas é o tempo que vai mostrar, conforme o que for acontecendo.

As janelas são criadas NO WINDOWS.
Elas não ficam presas ao programa, pelo contrário, é parte do programa que pode ficar preso à janela.
Mas se não tem mais a rotina de fechar janela porque o programa encerrou, clicar no fechar não vai fechar.
É onde entra encerrar a thread, ou fechar no gerenciador de tarefas.
Uma vez corrigido o erro, funciona normal.

Isto é só pra se preparar para o que pode acontecer.
Muitos já viram isso acontecer, e consideram normal.
Em multithread vai ser mais normal ainda.

Usando multithread

Enviado: 26 Fev 2025 14:25
por JoséQuintas
Uma situação de programa ZUMBI:

Imaginem um programa sem tela, e colocar lá Inkey(0)

Ok ?
É meio normal isso ?

Mas se não tem tela..... vai digitar ENTER aonde ?
O programa vai ficar eternamente esperando o ENTER.
Só mesmo fechando no gerenciador de tarefas.

Acho que esse seria um exemplo de um programa ZUMBI.
Ele tá lá rodando, e é obrigado a fechar no gerenciador de tarefas.

Durante o começo de uso pode ser normal fazer uma coisa dessas, ou em alguma situação eventual

Usando multithread

Enviado: 26 Fev 2025 14:40
por JoséQuintas
Compensa usar multithread ?

Sei lá... cada um que veja aonde pode usar.
Isso acontece com qualquer função do harbour, multithread não é diferente.
Você conhece a função, e quando tiver uma oportunidade faz uso dela ou não.
Multithread é a mesma coisa.

Em GUI já é normal ter várias janelas, pode colocar janelas pra fazer coisas diferentes.
Em GTWVG não é tão normal isso, começou por ser interessante ter várias janelas, continuou porque achei interessante ter arquivos independentes pra janelas independentes.
E agora continua interessante pra misturar LIBs.
Também achei interessante pra ter janelas com DBFs independentes, acabou com muito daquilo de ter que se preocupar com área aberta, índice aberto, filtro ativo, etc.

Cada um que veja se acha interessante usar multithread.

Talvez baste saber que existe, quando aparecer uma situação já sabe que pode usar.