Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Problemas con Threads (https://www.clubdelphi.com/foros/showthread.php?t=90799)

xangiesaurx 06-09-2016 23:59:06

Problemas con Threads
 
Hola a todos, me encuentro en un nuevo dile, estoy migrando un programa que tengo en Delphi 2010 a Delphi XE5, en el cual solo marca 2 errores:

[dcc32 Error] GenericBlockingQueue.pas: E2089 Invalid typecast

El código en donde marca el error es el siguiente:

Código Delphi [-]
procedure TBlockingQueueContentHandler< T >.NotifyDequeue(sender : TObject;
                                                        const item : T;
                                                        action : TCollectionNotification);
begin
  if (action = cnRemoved) and (TObject(item) <> nil) then  <------ Aquí marca el primero
    TObject(item).Free;                                    <------ Aquí marca el segundo 
end;

La declaración del thread se encuentra de la siguiente manera:

Código Delphi [-]
TBlockingQueueContentHandler< T > = class(TThread)
  private
    fBlockingQueue            : TBlockingQueue< T >;
    fOnNewItemInQueueFunction : TOnNewItemInQueueFunction;
  protected
    procedure Execute; override;
    procedure NotifyDequeue(sender : TObject; const item : T; action : TCollectionNotification); virtual;
  public
    constructor Create(blockingQueue : TBlockingQueue< T >;
                       onNewItemInQueueFunction : TOnNewItemInQueueFunction< T >;
                       isObjectDataT : Boolean = false);
    destructor Destroy; override;
  end;

La verdad, no entiendo muy bien los threads y me gustaría saber si podrían ayudarme.
De antemano gracias :)

AgustinOrtu 07-09-2016 00:48:47

Creo que el codigo quedo incompleto porque usas genericos, de lo contrario no compilaria

(Es un error del foro que Casimiro no quiere arreglar :p)

Asumiendo TBlockingQueueContentHandler <T>, el compilador no tiene informacion suficiente para poder comparar un generico T contra nil. Que pasaria si usara la cola asi:

TBlockingQueueContentHandler <Integer>? o TBlockingQueueContentHandler <TAlgunRecord>? Esos tipos no se pueden comparar contra nil

Lo que podes hacer es darle mas informacion al compilador, estableciendo constraints, que vendrian a ser restricciones

Los constraint se indican seguidos de : (dos puntos) luego de la declaracion del generico, por ejemplo:

TBlockingQueueContentHandler <T: class> --> indica que el tipo generico T es una clase (no podria ser un Integer, por ejemplo)

Revisa la documentacion para mas informacion

xangiesaurx 07-09-2016 00:58:52

Hola AgustinOrtu, antes que nada agradezco tu pronta respuesta, efectivamente hacen falta los <T> en varias partes :P
Revisare bien el código y daré una leída a lo que me has pasado, en cuanto tenga la solución pasaré a informar, así como cualquier problema que me encuentre (si se da el caso) en el proceso.

Solo una duda, este cambio es debido a que así se implementa en XE5? Por que en 2010 funciona sin problemas.

Casimiro Notevi 07-09-2016 01:02:23

Cita:

Empezado por AgustinOrtu (Mensaje 508570)
Creo que el codigo quedo incompleto porque usas genericos, de lo contrario no compilaria
(Es un error del foro que Casimiro no quiere arreglar :p)

Es un error de vbulletin, no tenemos el código fuente para modificarlo, no sé si habrá algún método para solucionarlo.
Creo recordar que si se ponen espacios "se los traga"
Código Delphi [-]
 < T >

xangiesaurx 09-09-2016 19:22:36

Que tal, buenos días a todos, vengo a comentarles que ya encontré la solución, hice unas modificaciones al código.

Código que daba errores:

Código Delphi [-]
procedure TBlockingQueueContentHandler< T >.NotifyDequeue(sender : TObject;
                                                        const item : T;
                                                        action : TCollectionNotification);
begin
  if (action = cnRemoved) and (TObject(item) <> nil) then 
    TObject(item).Free;                                    
end;

Código modificado:

Código Delphi [-]
procedure TBlockingQueueContentHandler< T >.NotifyDequeue(sender : TObject;
                                                        const item : T;
                                                        action : TCollectionNotification);
begin
  if (action = cnRemoved) and (PObject(@item)^ <> nil) then  
    PObject(@item)^.Free;                                    
end;

Una vez hechos esos cambios, el programa compilo sin problema :)
Muchas gracias a AgustinOrtu por su ayuda :D

AgustinOrtu 09-09-2016 20:37:31

Y funciona bien? Veo demasiados casteos no seguros en ese codigo :confused:

No se puede resolver usando constraints como dije mas arriba?

la clase TObjectList de Generics.Collections lo hace de esa manera:

Código Delphi [-]
  TObjectList< T: class > = class(TList< T >)
  protected
    procedure Notify(const Value: T; Action: TCollectionNotification); override;
  // ...

procedure TObjectList< T >.Notify(const Value: T; Action: TCollectionNotification);
begin
  inherited;
  if OwnsObjects and (Action = cnRemoved) then
    Value.DisposeOf;
end;

xangiesaurx 09-09-2016 21:04:13

Intenté con los constraints, pero era cambiar muchas declaraciones y otras partes del código.
Hice pruebas con los cambios que realice y todo funciona bien, igualmente, haré un branch nuevo y haré todos los cambios que me pide que haga usando los constraints.

AgustinOrtu 10-09-2016 00:56:44

Es mas que nada para que tu codigo quede mas seguro ^\||/

Esos cast forzosos son un peligro, y deberian evitarse a menos que sea como ultimo recurso; este no es el caso.

Otra cosa muy peligrosa es el operador '@', el principal problema que tiene es que de esa forma el compilador se pasa por encima el checkeo de tipos (todo vale) y te estas perdiendo una de las grandes ventajas de un lenguaje compilado, que detecta estos errores y te ahorran problemas al momento de correr tu aplicacion

Fijate que estas casteando la direccion de memoria de tu parametro a un puntero a TObject y luego accediendo al TObject referenciado por el puntero. Es como demasiado "hardcore" :D:D

maeyanes 13-09-2016 17:33:12

Hola...

Cita:

Empezado por xangiesaurx (Mensaje 508651)
Intenté con los constraints, pero era cambiar muchas declaraciones y otras partes del código.
Hice pruebas con los cambios que realice y todo funciona bien, igualmente, haré un branch nuevo y haré todos los cambios que me pide que haga usando los constraints.

Para casos como este es que existe algo llamado refactoring


Saludos...


La franja horaria es GMT +2. Ahora son las 18:13:00.

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