Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   EAccessViolation usando Hilos (https://www.clubdelphi.com/foros/showthread.php?t=67839)

Thoronluin 08-05-2010 21:19:37

EAccessViolation usando Hilos
 
Hola compañeros:

Tengo un pequeño problemilla. Estoy creando un pequeño programa que en una de las partes crea un hilo que debe ser ejecutado para no quedar bloqueado por otro proceso, el problema es que cuando me ejecuta el hilo me da el siguiente error:

Debugger Exception Notification
Project Servicio.exe raised exception class EAccessViolation with message ' Access violation at Address 004E8B49 in module 'Servicio.exe'. Read of addres 00000667'.

Para poder estudiarlo mejor he incluido un botón que me crea el hilo en lugar de ser otros procesos quienes me lo creen y he descubierto que si lo que ejecuto es un "Showmessage" la cosa va bien pero si otro objeto me da el error en esa línea como si no estuviera creado. El código es el siguiente:

Código Delphi [-]
TPruebaMensaje = class(TThread)
   private
   protected
   public
      procedure Execute; override;
      procedure UpdateProgress;
 end;  

TVentana_Principal = class(TForm)
...

...
Procedure TPruebaMensaje.Execute;
begin
   Synchronize(UpdateProgress);
end;

procedure TVentana_Principal.Button4Click(Sender: TObject);
var
   MensajeThread: TPruebaMensaje;
begin
   MensajeThread := TPruebaMensaje.Create(True);
   MensajeThread.FreeOnTerminate:=true;
   MensajeThread.Resume;
end;

Procedure TPruebaMensaje.UpdateProgress;
begin
   showmessage('hola');        // Prueba 1
   // Ventana_Principal.Memo1.Lines.Add('pepe'); // Prueba 2
end;

Es la primera vez que inicio un hilo en el foro así que espero no haberme saltado nada de la guía de estilo, si es así por favor disculpen y comentenme lo que sea.

Muchas gracias por su tiempo y paciencia.

Neftali [Germán.Estévez] 10-05-2010 16:35:57

Debes tener en cuenta de a qué cosas accedes desde dentro del hilo.
Si accesdes a elementos externos al hilo, debes hacerlo desde el Synchronize.

Thoronluin 10-05-2010 23:41:13

Hola Neftali:

Ante todo muchas gracias por tu pronta respuesta. Con ella, más los dos ejemplos que ví en tu web las cosas me han quedado más claras.

Corrígeme si me equivoco. Puedo:

O incluir el Memo en la declaración del Thread:

Código Delphi [-]
TPruebaMensaje = class(TThread)
   private
   protected
   public
      Memo1: Tmemo;
      procedure Execute; override;
      procedure UpdateProgress;
 end;

O usar la función Synchronize para ejecutar la acción:

Código Delphi [-]
Procedure TPruebaMensaje.Execute;
begin
   Synchronize(Ventana_Principal.Memo1.Lines.Add('pepe'));
end;

O definir la función UpdateProgress como perteneciente a Ventana_Principal y ejecutar:

Código Delphi [-]
Procedure TPruebaMensaje.Execute;
begin
   Synchronize(UpdateProgress);
end;

Muchas gracias por tu ayuda, estoy ansioso por probarlo mañana a primera hora :D.

Saludos

Thoronluin 11-05-2010 13:42:19

He probado las tres cosas pero ninguna funcionó. Lo unico que parece que me elimina el error es modicar el código comos sigue:

Código Delphi [-]
procedure TVentana_Principal.Button4Click(Sender: TObject);
var
   MensajeThread: TPruebaMensaje;
begin
   MensajeThread := TPruebaMensaje.Create(False);
   //MensajeThread.FreeOnTerminate:=true;
   //MensajeThread.Resume;
end;

Pero en ese caso cada vez que se ejecute la línea:

Código Delphi [-]
MensajeThread := TPruebaMensaje.Create(False);

Se me crearía una nueva instancia, el problema ahora es, que las antiguas si no las he liberado posiblemente me estén ahí consumiendo recursos ¿Me equivoco?.

En el ejemplo he puesto un botón pero esas líneas de código las va a llamar un execute de un TIdTCPserver, ejecutandose muchas veces durante la vida del programa.

Saludos.

Neftali [Germán.Estévez] 11-05-2010 14:05:43

Cita:

Empezado por Thoronluin (Mensaje 363496)

O incluir el Memo en la declaración del Thread:... Synchronize(Ventana_Principal.Memo1.Lines.Add('pepe'));


Puedes definir el memo propiedad (pública) del Thread, por ejemplo, o pasarlo como parámetro en el Create (redefiniendolo).
Cuando crees el Thread o después, si lo creas suspendido, asignas el memo del programa principal a tu propiedad del thread. Luego puedes accederlo.
Código Delphi [-]
TPruebaMensaje = class(TThread)
   private
   protected
   public
      MemoMain: Tmemo;
      procedure Execute; override;
      procedure UpdateProgress;
 end;
...

var
   MensajeThread: TPruebaMensaje;
begin
   MensajeThread := TPruebaMensaje.Create(True);
   MensajeThread.MemoMain := memo1;
   MensajeThread.FreeOnTerminate:=true;
...
Luego, desde el thread, no debes acceder al memo del programa principal:

Código Delphi [-]
Synchronize(Ventana_Principal.Memo1.Lines.Add('pepe'));

Si no al memo del Thread.

Código Delphi [-]
Synchronize(MemoMain.Lines.Add('pepe'));

Thoronluin 11-05-2010 14:17:16

Muchísimas gracias por la respuesta y por la velocidad de ésta. Voy a intentarlo así, ya te contaré.

Saludos

Thoronluin 11-05-2010 16:20:29

Lo he probado, funciona genial, muchísimas gracias por todo.

Saludos


La franja horaria es GMT +2. Ahora son las 01:23:43.

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