Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   API de Windows (https://www.clubdelphi.com/foros/forumdisplay.php?f=7)
-   -   Thread bendito thread...se me pierde la ventana (https://www.clubdelphi.com/foros/showthread.php?t=29620)

Seba.F1 26-01-2006 23:35:20

Thread bendito thread...se me pierde la ventana
 
Hola gente como andan? llevo mas de 3 horas buscando en los foros de club delphi e internet algo que me ayude con mi problema pero no encuentro nada, si no les molesta a los que mas saben por favor denme una mano, o un pie o algo por favor!!!!!!!! estoy por volverme loco.

EL PROBLEMA
He desarrollado una aplicación que entre muchas cosas, lee datos de una balanza electrónica que pesa camiones (cuando comence con el desarrollo ya estaba). La cuestión es que esta balanza usa un ejecutable en DOS (si Disk Operating Sistem de Micro...), cuando lo ejecuto con cierta sintaxis me devuelve el valor del peso en un archivo .txt. Hasta aca todo bien. Por cuestiones de tiempo (demoras del archivito, mostrar los datos, etc) tuve que implementar un thread para que la aplicación pueda realizar otras tareas mientras pesa los camiones, y ejecuto dentro del thread el programita de la balanza, luego leo el archivo .txt y muestro el numerito en LA aplicación, cuando deja de pesar, se termina el thread, imprime el ticket y cuando cierro la ventana de la balanza, puuuuuuuuffffff,!"·$·$|@#~&·$&|@#~%&|@#~€|34% me tira el siguiente error (obviamente le meti un par de try except... y muestra un lindo mensajito).

Error Win32 Code1400
El identificador de la ventana no es válido

todo bien hasta que se quiere volver a abrir la ventana de la balanza.

Ya existe un componente con el nombre F_Balanza.

y no me lo deja crear, y cuando cierro la aplicaciópn paaaaaaassfff

violacion de acceso a la direccion 7c928fea en el módulo ntdll.dll

aca va el codigo de mi thread, junto con el que dispara el ejecutable de la balanza.

por favor les pido que si alguien me pude decir donde le estoy errando, porque ya no veo nada.


Código Delphi [-]
function T_Lectura_Balanza.Ejecutar(const AppName, Params:String):THandle;
var
   ProcInfo:TProcessInformation;
   Info:TStartupInfo;
begin
     FillChar(Info,SizeOf(Info),0);
     Info.cb:=SizeOf(Info);
     Info.dwFlags:=STARTF_USESHOWWINDOW;
     info.wShowWindow:=SW_HIDE;
     if not CreateProcess(nil, pchar(AppName+' '+Params),nil,nil,False,0,nil,nil,Info,ProcInfo) then
        raise Exception.Create('No se puede iniciar la lectura de la balanza.');
     Result:=ProcInfo.hProcess;
end;
procedure T_Lectura_Balanza.Esperar(H:THandle);
begin
     while WaitForSingleObject(H,100)=WAIT_TIMEOUT do
           begin
                Application.ProcessMessages;
                if Application.Terminated then
                   Break;
                if F_Balanza.Terminar then
                   Break;
           end;
end;
 
 
procedure T_Lectura_Balanza.Execute;
begin      Linea_Comando:=MD_Config.IBQ_CONFIGLINEA_COMANDO_BALANZA.AsString;
     repeat
           try
              Esperar(Ejecutar(Linea_Comando,''));
              Archivo_Peso:=F_Principal.Dir+'Peso';
              F_Balanza.Memo_Peso.Lines.LoadFromFile(Archivo_Peso);
              Archivo_Peso:=F_Balanza.Memo_Peso.Lines[0];
              if Archivo_Peso='E' then
                 begin
                      F_Balanza.Img_Error.Visible:=True;
                 end
              else
                  begin
                       F_Balanza.Img_Error.Visible:=False;
                       Peso:=Copy(Archivo_Peso,2,(Length(Archivo_Peso)-1));
                       try
                          Long_:=StrToFloat(Peso);
                       except
                             Long_:=0;
                       end;
                       if Long_=0 then
                          F_Balanza.Img_Cero.Visible:=True
                       else
                           F_Balanza.Img_Cero.Visible:=False;
                       F_Balanza.Kg:=Long_;
                       Decodificar_Numero(Long_,CM,DM,UM,C,D,U);
                       Mostrar(CM,DM,UM,C,D,U);
                  end;
          except
                 Decodificar_Numero(0,CM,DM,UM,C,D,U);
                 Mostrar(CM,DM,UM,C,D,U);
                 F_Balanza.Img_Cero.Visible:=True;
           end;
     until F_Balanza.Terminar;
end;

desde ya muchas gracias.

roman 27-01-2006 00:11:36

No entiendo demasiado de hilos pero siento que tu código está muy enredado.

¿Para qué pones al WaitForSingleObject dentro de un while? En principio, no se pasará de esa línea hasta que no se cumpla el tiempo especificado y si no quieres que termine después de ese tiempo pones INFINITE como timeout y sólo terminará hasta que se cumpla la condición (que termine la otra aplicación)

Y así mismo, no entiendo para qué usas un repeat en el método execute. Si el WaitForSingleObject esta en INFINITE, el método Execute no terminará hasta que no acabe la otra aplicación.

Por otra parte no estoy seguro de si realmente es necesario usar un thread aparte. Cuando uses la balanza podrías poner algo como:

Código Delphi [-]
EjecutarBalanza;

DeleteFile('archivo.txt');

repeat
  Application.ProcessMessages;
until FileExists('balanza.txt') or Application.Terminated;

ShowMessage('Ya terminó');

// Saludos

seoane 27-01-2006 01:21:43

Solo un par de detalles. No deberias de utilizar componentes de un formulario desde un Thread sin usar el metodo "Synchronize".

Segundo, como haces para cerrar y mostrar la ventana F_Balanza porque puede que el problema este ahi y no en el thread.

Por ultimo la solucion de Roman me parece sencilla y deberia de funcionar de maravilla. Aunque al escribirlo CREO que no lo hizo en el orden correcto, deberia de ser:

Código:

DeleteFile('balanza.txt');
EjecutarBalanza;
repeat
  Application.ProcessMessages;
until FileExists('balanza.txt') or Application.Terminated;
ShowMessage('Ya terminó');

Si me equivoco, perdoname ...

roman 27-01-2006 01:36:24

Cita:

Empezado por seoane
CREO que no lo hizo en el orden correcto, deberia de ser:

¡Claro!, Tienes toda la razón. Probé el resto de la solución pero no tenía una de esas balanzas a la mano :D. Gracias por la aclaración.

// Saludos

Seba.F1 28-01-2006 13:16:12

aclaración sobre la consulta
 
No entiendo demasiado de hilos pero siento que tu código está muy enredado.

hola roman como andás agradezco mucho la respuesta.
te aclaro algunas cositas porque no fui muy claro.

¿Para qué pones al WaitForSingleObject dentro de un while? En principio, no se pasará de esa línea hasta que no se cumpla el tiempo especificado y si no quieres que termine después de ese tiempo pones INFINITE como timeout y sólo terminará hasta que se cumpla la condición (que termine la otra aplicación)

el WaitForSingleObject lo puse para que espere un ratito y se fije en la cola de mensajes a ver cuando termina la ejecución de la aplicacion cuando encuentra la finalización sale del while.

Y así mismo, no entiendo para qué usas un repeat en el método execute. Si el WaitForSingleObject esta en INFINITE, el método Execute no terminará hasta que no acabe la otra aplicación.

el repeat lo utilizo como pooling para ejecutar las otras tareas, hasta que el formulario F_Balanza dice que termine, ya que los camiones están durante algun tiempo en la balanza y se les agrega o saca granos para llegar a los kg exactos con los que pueden usar las rutas.

Por otra parte no estoy seguro de si realmente es necesario usar un thread aparte. Cuando uses la balanza podrías poner algo como:

Código Delphi [-]
EjecutarBalanza;
 
DeleteFile('archivo.txt');
 
repeat
Application.ProcessMessages;
until FileExists('balanza.txt') or Application.Terminated;
 
ShowMessage('Ya terminó');

esta version la estoy probando.
si se les ocurre algo nuevo lo agradecere mucho.
un saludo a todos.

// Saludos

Seba.F1 02-02-2006 00:16:30

Ya lo solucioné
 
Gracias chicos por la ayuda, la solucion la encontre en una combinación de las soluciones planteadas, por un lado roman utilice el borrar y verificar la existencia del archivo delpeso, con eso se me acabaron los problemas con la lectura del archivo, y por otro lado con el infinite en el waitforsingleobject, con eso anduvo barbaro.
por otro lado gracias seoane por el dato del syncronize no sabia que lo tenia que usar es mas el tthread te lo sugiere cuando lo creas, que tonto de mi parte.

bueno chicos nuevamente gracias por la ayuda y solucion de mi problema. saludos seba.:o


La franja horaria es GMT +2. Ahora son las 02:26:54.

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