Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 02-09-2020
RobertPolson RobertPolson is offline
Registrado
 
Registrado: sep 2020
Posts: 1
Poder: 0
RobertPolson Va por buen camino
Delphi Calculadora en 2 hilos

Buenos días,
He desarrollado una calculadora en Delphi Berlin 10.1, con un hilo que se encarga de hacer los cálculos que se le indiquen cuando se pulse el boton '='. Cuando este botón se pulsa se realiza una espera de 3seg para comprobar que, durante la ejecución del hilo, se pueden seguir pulsando botones, por ejemplo si se quiere borrar todo y que el cálculo no se realice finalmente pues que me permita hacerlo. El problema es que durante el primer cálculo sí me permite pulsar botones, pero en los siguientes la pantalla se queda bloqueada hasta que acaba el cálculo.
En cualquier caso el boton de borrar lo he programado para que finalice el hilo y ni siquiera en el primer calculo lo cierra. Pulso, borra la pantalla pero pasados 3 segundos me muestra el resultado. Adjunto el código por si alguien me podría ayudar...Mil gracias de antemano.

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ToolWin, Vcl.ComCtrls, Vcl.StdCtrls;

type
TOperacion = (NOOPER, SUMA, RESTA, MULTI, DIVI);

TThreadCaculador = class(TThread)
private
protected
public
procedure Execute; override;
end;

TForm1 = class(TForm)
LabelCreador: TLabel;
EditNumero: TEdit;
boton0: TButton;
boton1: TButton;
boton2: TButton;
boton3: TButton;
boton4: TButton;
boton5: TButton;
boton6: TButton;
boton7: TButton;
boton8: TButton;
boton9: TButton;
botonDiv: TButton;
botonMult: TButton;
botonResta: TButton;
botonSigno: TButton;
botonComa: TButton;
botonSuma: TButton;
LabelOperacion: TLabel;
botonCalcular: TButton;
botonClear: TButton;
LabelEspera: TLabel;
procedure boton0Click(Sender: TObject);
procedure boton1Click(Sender: TObject);
procedure boton2Click(Sender: TObject);
procedure boton3Click(Sender: TObject);
procedure boton4Click(Sender: TObject);
procedure boton5Click(Sender: TObject);
procedure boton6Click(Sender: TObject);
procedure boton7Click(Sender: TObject);
procedure boton8Click(Sender: TObject);
procedure boton9Click(Sender: TObject);
procedure botonSumaClick(Sender: TObject);
procedure botonRestaClick(Sender: TObject);
procedure botonMultClick(Sender: TObject);
procedure botonDivClick(Sender: TObject);
procedure botonCalcularClick(Sender: TObject);
procedure botonClearClick(Sender: TObject);
procedure botonComaClick(Sender: TObject);
procedure botonSignoClick(Sender: TObject);
private
{ Private declarations }
threadCalculador : TThreadCaculador;
public
{ Public declarations }
valor1, valor2 : real; // Operandos
operacion : TOperacion; // Operación (ver constantes de arriba)
end;

var
Form1: TForm1;
HiloCorriendo : Boolean;

implementation



{$R *.dfm}
{------------------------------------------------------------------------------}
{ TThreadCaculador }
{------------------------------------------------------------------------------}






procedure TThreadCaculador.Execute;
var
resultado : real;
i : Integer;
begin
// Salir si no se ha indicado una operacion
if Form1.operacion = NOOPER then exit;
// Evitar division por cero
if (Form1.operacion = DIVI) and (Form1.valor2 = 0) then exit;
HiloCorriendo := True;
// Espera: imprimir '.' cada segundo en la GUI
for i := 1 to 3 do
begin
Sleep(1000);
Synchronize( // Para ejecutar en el hilo principal
procedure
begin
Form1.LabelEspera.Caption := Form1.LabelEspera.Caption + '.'
end
)
end;
Form1.LabelEspera.Caption := '';
// Realizar cálculo
resultado := 0;
if Form1.operacion = SUMA then resultado := Form1.valor1 + Form1.valor2
else if Form1.operacion = RESTA then resultado := Form1.valor1 - Form1.valor2
else if Form1.operacion = MULTI then resultado := Form1.valor1 * Form1.valor2
else if Form1.operacion = DIVI then resultado := Form1.valor1 / Form1.valor2;
// valor1 ahora sera el resultado tambien
//Form1.valor1 := resultado;

// Actualizar valor en la GUI
Synchronize( // Para ejecutar en el hilo principal
procedure
begin
Form1.EditNumero.Text := FloatToStr(resultado);
Form1.operacion := NOOPER;
end
)
end;

{------------------------------------------------------------------------------}
{ TForm1 }
{------------------------------------------------------------------------------}

procedure TForm1.boton0Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '0' else
EditNumero.Text := EditNumero.Text + '0';
end;

procedure TForm1.boton1Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '1' else
EditNumero.Text := EditNumero.Text + '1';
end;

procedure TForm1.boton2Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '2' else
EditNumero.Text := EditNumero.Text + '2';
end;

procedure TForm1.boton3Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '3' else
EditNumero.Text := EditNumero.Text + '3';
end;

procedure TForm1.boton4Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '4' else
EditNumero.Text := EditNumero.Text + '4';
end;

procedure TForm1.boton5Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '5' else
EditNumero.Text := EditNumero.Text + '5';
end;

procedure TForm1.boton6Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '6' else
EditNumero.Text := EditNumero.Text + '6';
end;

procedure TForm1.boton7Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '7' else
EditNumero.Text := EditNumero.Text + '7';
end;

procedure TForm1.boton8Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '8' else
EditNumero.Text := EditNumero.Text + '8';
end;

procedure TForm1.boton9Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '9' else
EditNumero.Text := EditNumero.Text + '9';
end;

procedure TForm1.botonClearClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
LabelOperacion.Caption := '';
EditNumero.Text := '0';
end;

procedure TForm1.botonComaClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
EditNumero.Text := EditNumero.Text + ',';
end;

procedure TForm1.botonSignoClick(Sender: TObject);
var
tmp : real;
begin
tmp := StrToFloat(EditNumero.Text);
tmp := -tmp;
EditNumero.Text := FloatToStr(tmp);
end;

procedure TForm1.botonSumaClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' + ';
EditNumero.Text := '0';
operacion := SUMA;
end;

procedure TForm1.botonRestaClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' - ';
EditNumero.Text := '0';
operacion := RESTA;
end;

procedure TForm1.botonMultClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' x ';
EditNumero.Text := '0';
operacion := MULTI;
end;

procedure TForm1.botonDivClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' / ';
EditNumero.Text := '0';
operacion := DIVI;
end;

procedure TForm1.botonCalcularClick(Sender: TObject);
begin
Form1.valor2 := StrToFloat(Form1.EditNumero.Text);
Form1.LabelOperacion.Caption := Form1.LabelOperacion.Caption + Form1.EditNumero.Text + ' ';
Form1.EditNumero.Text := '';

// Si no he creado ya el thread de cálculo, lo creo (se ejecuta automáticamente)
// Si ya está creado y ha acabado la petición anterior, lo acabo y lo vuelvo a ejecutar
if (not Assigned(threadCalculador)) then
begin
threadCalculador := TThreadCaculador.Create;
threadCalculador.FreeOnTerminate := True;
threadCalculador.Priority := tpLower;
end
else if threadCalculador.Finished then
begin
threadCalculador.Terminate;
threadCalculador.Execute;
end
end;

end.
Responder Con Cita
  #2  
Antiguo 02-09-2020
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.057
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Bienvenido a clubdelphi, por favor, recuerda leer nuestra guia de estilo, gracias.
¿Para iOS/OSX?

No olvides usar las etiquetas para código:
Responder Con Cita
  #3  
Antiguo 02-09-2020
jlrmdevilReturn jlrmdevilReturn is offline
Registrado
 
Registrado: sep 2020
Posts: 2
Poder: 0
jlrmdevilReturn Va por buen camino
No sera falla de logica???... por que en teoria hace lo que tiene que hacer...Por cierto... y el codigo de borrar, aclarar o como se diga en tu pais (en las calculadoras es la tecla AC de all clear), por que no veo un boton para borrar como mencionas.

Última edición por jlrmdevilReturn fecha: 02-09-2020 a las 21:11:48. Razón: Extender respuesta
Responder Con Cita
  #4  
Antiguo 03-09-2020
Avatar de movorack
[movorack] movorack is offline
Miguel A. Valero
 
Registrado: feb 2007
Ubicación: Bogotá - Colombia
Posts: 1.346
Poder: 20
movorack Va camino a la famamovorack Va camino a la fama
Hola, buenos días.

Para que tengas en cuenta:

- En el Execute de tu hilo estás usando elementos del hilo principal, al hilo deberían llegar los datos desligados de algún componente del hilo principal. Podrías crear algunas propiedades en el hilo para almacenar los valores de operacion, valor1 y valor2.
- Cuando usas Sleep dentro del Execute, estás afectando a toda la aplicación. No solo el hilo

Te recomiendo mires algunos artículos relacionados de este sitio
__________________
Buena caza y buen remar... http://mivaler.blogspot.com
Responder Con Cita
  #5  
Antiguo 07-09-2020
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Hola RobertPolson.

No he revisado tu código, porque no lo colocaste como indicó Casimiro Notevi en la primera respuesta, pero de todas formas no estoy seguro de que necesites crear un hilo para lo que deseas conseguir.

Creo que podrías usar un par de variables "bandera" (tipo Boolean). La primera para indicar si en ese momento se está ejecutando un cálculo, y la segunda para indicar si se ha presionado otro botón durante un proceso de cálculo que no ha terminado.

La clave está en que durante el proceso de cálculo llames a Application.ProcessMessages cada cierto tiempo o varias veces entre las instrucciones de tu cálculo para darle oportunidad al usuario de interactuar con la pantalla aunque no haya terminado de realizarse dicho cálculo. La acción de presionar un botón evaluaría la primera de las variables que te mencioné, que de ser True, pondría en True la otra de las variables y dejaría en "cola de espera" la tarea de ese botón. Mientras que el proceso de cálculo, después de cada llamada a ProcessMessages revisaría si esta segunda variable está en True y por lo tanto determinaría si debe abandonar el cálculo dependiendo de cuál botón se haya presionado durante el proceso.

Espero haberme dado a entender. Saludos.

Última edición por Al González fecha: 07-09-2020 a las 02:27:27.
Responder Con Cita
  #6  
Antiguo 07-09-2020
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.913
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
No entiendo porque una calculadora necesita multi-hilos. Los computadores son rapidos, mas en cosas numericas:

https://computers-are-fast.github.io

Código PHP:
#!/usr/bin/env python

# Number to guess: How many iterations of an
# empty loop can we go through in a second?

def f(NUMBER):
    for 
_ in xrange(NUMBER):
        
pass

import sys
f
(int(sys.argv[1])) 
En 1 segundo hace aprox. 68'000.000 millones de ciclos. Y eso, python, que es "lento" en estas cosas.

---

Meterle hilos a un programa es HACERLO MAS LENTO para ganar "fluidez" al hacer multiples cosas. Uno PRIMERO debe aprender a sacarle el jugo al codigo "single-thread" y solamente ir a los hilos si y solo si es necesario. Estando en esa necesidad, es MEJOR utilizar una libreria que abstraiga el tema, porque usar hilos a "pelo" es notoriamente dificil y eso en manos de expertos...
__________________
El malabarista.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Problemas con Calculadora en Delphi jhony2201 Bibliotecas de código fuente 4 01-08-2016 10:32:04
Calculadora hecha en delphi alquimista Varios 35 29-12-2014 19:04:03
¿Como mostrar el calculo hecho por una calculadora?, realizada en Delphi Subliminalz Varios 5 30-04-2013 18:02:49
Calculadora Cientifica Gráfica en Delphi, paradox y OpenGL Apokalipsis Varios 5 26-01-2011 07:09:57
Calculadora en delphi 7 eudy.net Varios 15 10-03-2007 05:35:02


La franja horaria es GMT +2. Ahora son las 23:37:29.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi