![]() |
![]() |
| Paypal | FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
|||||||
| Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Buscar | Temas de Hoy | Marcar Foros Como Leídos |
![]() |
|
|
Herramientas | Buscar en Tema | Desplegado |
|
#1
|
||||
|
||||
|
Problemas con los hilos en Builder
Hola amigos, aqui otra vez con problemas
.El problema que tengo ahora es que estoy probando el manejo de un hilo y si uso Terminate() y FreeOnTerminate = true le doy y se termina el hilo y se destruye pero, si uso Suspend() el hilo no se detiene y sigue trabajando. Probé a poner FreeOnTerminate = false y usar WaitFor() despues de Suspend(), Resume(), o Terminate() pero me encuentro con que ejecuta cualquiera de esas lineas y llega al WaitFor() y se queda congelado todo, tanto el interfaz como el hilo. No se por qué pasa esto y ademas tuve que poner un Application->ProcessMessage() para que procese los mensajes y me deje trabajar sobre el form para poder pulsar los botones ya que si no es así no me deja hacer nada y el form se congela mientras corre el hilo ¿no se supone que los hilos son entre otras cosas para evitar eso? Es muy cortito asi que lo pongo aquí: THilo.cpp: Código:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "THilo.h"
#include "Unit1.h"
#pragma package(smart_init)
__fastcall THilo::THilo(bool CreateSuspended)
: TThread(CreateSuspended)
{
Priority = tpNormal;
FreeOnTerminate = false;
}
//---------------------------------------------------------------------------
void __fastcall THilo::Execute()
{
Synchronize(Bucle);
}
//---------------------------------------------------------------------------
void __fastcall THilo::Bucle()
{
while(!Terminated)
{
Form1->Caption = Form1->Caption.ToDouble() + 1;
Application->ProcessMessages();
Sleep(1000);
}
}
Código:
//---------------------------------------------------------------------------
#ifndef THiloH
#define THiloH
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
class THilo : public TThread
{
private:
protected:
void __fastcall Execute();
void __fastcall THilo::Bucle();
public:
__fastcall THilo(bool CreateSuspended);
};
//---------------------------------------------------------------------------
#endif
Código:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "THilo.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
THilo *Hilo;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonCrearClick(TObject *Sender)
{
Hilo = new THilo(false);
ButtonCrear->Enabled = false;
ButtonPausa->Enabled = true;
ButtonAbortar->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonContinuarClick(TObject *Sender)
{
Hilo->Resume();
Hilo->WaitFor();
ButtonContinuar->Enabled = false;
ButtonPausa->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonPausaClick(TObject *Sender)
{
Hilo->Suspend();
Hilo->WaitFor();
ButtonContinuar->Enabled = true;
ButtonPausa->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonAbortarClick(TObject *Sender)
{
Hilo->Terminate();
Hilo->WaitFor();
delete Hilo;
ButtonCrear->Enabled = true;
ButtonPausa->Enabled = false;
ButtonContinuar->Enabled = false;
ButtonAbortar->Enabled = false;
}
//---------------------------------------------------------------------------
Estas cosas no me pasan usando las Apis de windows ResumeThread(), SuspendThread(), CreateThread(), y TerminateThread() ¿por que pasa con el que nos da Borland? |
|
#2
|
||||
|
||||
|
Acabo de ver que es un problema con Synchronize(), o sea, si uso Synchronize no me funciona ni Resume(), ni Suspend(), WaitFor(). Pero creo que voy a necesitar del uso de Synchronize ¿como lo hago?
|
|
#3
|
||||
|
||||
|
bueno ya lo conseguí. Me explicaron que es porque Synchronize es para sincronizar entre hilos y que no habia que usarlo para todo y despues de algunos cambios ya fue. Ahora me encuentro con otro problema, necesito pasar variables desde donde creo el hilo hasta el execute y que dichas variables esten accesibles en ambos sitios. No puedo usar variables globales. ¿Como le puedo pasar variables al hilo? Con THilo hilo = new *THilo() solo puedo pasarle el estado al crearse. Probé a pasarle mas variables modificandola en la clase y me daba un error sobre que estaba haciendo una funcion abstracta o algo asi.
|
|
#4
|
||||
|
||||
|
Ahora me encuentro con otro problema, tengo usa serie de funciones en unit1 y quiero ejecutarlas desde el hilo pero por supuesto el hilo no sabe ni que existen ¿como hago para poder ejecutarlas desde el hilo?
|
|
#5
|
||||
|
||||
|
Cita:
Saludos. |
|
#6
|
||||
|
||||
|
No me funciona o no se como hacerlo. Tengo esto en el Execute del hilo:
Código:
case EXCEPTION_SINGLE_STEP:
if(FuncSingleStep != NULL)
{
try{
FuncSingleStep();
}
catch(...){
}
}
dwContinueStatus = OnSingleStep(&DebugEv);
break;
case EXCEPTION_GUARD_PAGE_VIOLATION:
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
break;
y en el .h donde están las funciones tengo esto: Código:
#include <vcl.h>
#include "THiloDebugger.h"
#ifndef DEBUGGERH
#define DEBUGGERH
#define EXCEPTION_GUARD_PAGE_VIOLATION 0x80000001L
//tipos de funciones eventos
typedef void __fastcall(__closure* SYSTEMBREAKPOINT)(void);
typedef void __fastcall(__closure* BREAKPOINT)(DWORD);
typedef void __fastcall(__closure* EXCEPTION)(int,DWORD);
typedef void __fastcall(__closure* CREATEPROCESS)(CREATE_PROCESS_DEBUG_INFO *);
typedef void __fastcall(__closure* EXITPROCESS)(EXIT_PROCESS_DEBUG_INFO *);
typedef void __fastcall(__closure* CREATETHREAD)(CREATE_THREAD_DEBUG_INFO *);
typedef void __fastcall(__closure* EXITTHREAD)(EXIT_THREAD_DEBUG_INFO *);
typedef void __fastcall(__closure* LOADDLL)(LOAD_DLL_DEBUG_INFO *);
typedef void __fastcall(__closure* UNLOADDLL)(UNLOAD_DLL_DEBUG_INFO *);
typedef void __fastcall(__closure* OUTPUTSTRING)(OUTPUT_DEBUG_STRING_INFO *);
typedef void __fastcall(__closure* RIP)(RIP_INFO *);
typedef void __fastcall(__closure* SINGLESTEP)(void);
typedef struct{
SYSTEMBREAKPOINT FuncSystemBreakPoint;
BREAKPOINT FuncBPs;
EXCEPTION FuncException;
CREATEPROCESS FuncCreateProcess;
EXITPROCESS FuncExitProcess;
CREATETHREAD FuncCreateThread;
EXITTHREAD FuncExitThread;
LOADDLL FuncLoadDLL;
UNLOADDLL FuncUnLoadDLL;
OUTPUTSTRING FuncOutPutString;
RIP FuncRIP;
SINGLESTEP FuncSingleStep;
}TEventDebugCallBack;
class TDebugger
{
//estructura debug_event requerida para obtener los eventos del proceso y poder gestionarlos
public:
//variable necesaria para salir cuando lo deseemos del bucle
bool Terminated;
AnsiString PathFile;
bool DebugExists;
TDebugger();
~TDebugger();
bool InitDebug(void); //Carga la víctima
void LoopDebug(void); // inicio de la depuración
// Solo tienen sentido si el depurador está parado
AnsiString ReadString(DWORD, int);
bool SetBP(DWORD);
bool RemoveBP(DWORD);
bool SetHBP(DWORD, int, int, int);
bool RemoveHBP(int);
bool RemoveAllHBP(void);
DWORD GetEAX(void);
DWORD GetECX(void);
DWORD GetEDX(void);
DWORD GetEBX(void);
DWORD GetESP(void);
DWORD GetEBP(void);
DWORD GetESI(void);
DWORD GetEDI(void);
DWORD GetEIP(void);
void SetSingleStep(void);
DWORD GetLastAddress(void);
void SetEAX(DWORD Valor);
void SetECX(DWORD Valor);
void SetEDX(DWORD Valor);
void SetEBX(DWORD Valor);
void SetESP(DWORD Valor);
void SetEBP(DWORD Valor);
void SetESI(DWORD Valor);
void SetEDI(DWORD Valor);
void SetEIP(DWORD Valor);
// Establecer los CallBacks
void SetOnSystemBreakPoint(SYSTEMBREAKPOINT);
void SetOnBPs(BREAKPOINT);
void SetOnException(EXCEPTION);
void SetOnCreateProcess(CREATEPROCESS);
void SetOnExitProcess(EXITPROCESS);
void SetOnCreateThread(CREATETHREAD);
void SetOnExitThread(EXITTHREAD);
void SetOnLoadDll(LOADDLL);
void SetOnUnLoadDll(UNLOADDLL);
void SetOnOutPutString(OUTPUTSTRING);
void SetOnRIP(RIP);
void SetOnSingleStep(SINGLESTEP);
void SetCallBack(TEventDebugCallBack *);
//**************************************
private:
BOOL SearchBPOnList(DWORD, BYTE *, int *, bool *);
// Eventos del hilo de depuración
DWORD OnCreateThreadDebugEvent(LPDEBUG_EVENT);
DWORD OnCreateProcessDebugEvent(LPDEBUG_EVENT);
DWORD OnExitThreadDebugEvent(LPDEBUG_EVENT);
DWORD OnExitProcessDebugEvent(LPDEBUG_EVENT);
DWORD OnLoadDllDebugEvent(LPDEBUG_EVENT);
DWORD OnUnloadDllDebugEvent(LPDEBUG_EVENT);
DWORD OnOutputDebugStringEvent(LPDEBUG_EVENT);
DWORD OnRipEvent(LPDEBUG_EVENT);
// tratamiento de excepciones
DWORD OnSingleStep(LPDEBUG_EVENT);
DWORD OnBreakpointDebugEvent(LPDEBUG_EVENT);
DWORD LastExceptionAddress;
protected:
//Para la gestion de los BPs
TList *ListaBPs; //Lista para la gestion de las estructuras BP
int pos; //Para recuperar la posicion que ocupa un BP en la lista
bool estadoBP; //Lo uso para saber si el usuario quiso eliminar el BP de la lista
DWORD FAddrOnBPSS; // Dirección del BP a restaurar en EXCEPTION_SINGLE_STEP
BYTE bOriginal; //Lo uso para obtener el byte original de la posición del BP
//Estructura para cada BP
typedef struct TBP
{
DWORD dir;
BYTE byteOriginal;
bool estado; //true activado, false desactivado
}*pBP;
//Estructura startup requerida para createprocess
STARTUPINFO si;
//estructura process information requerida para el pid
PROCESS_INFORMATION pi;
//estructura context contiene los valores de los registros
#pragma align 8 // no recuerdo bien si esto se hace con un #pragma
CONTEXT con;
// Funciones de callback
SYSTEMBREAKPOINT FuncSystemBreakPoint;
BREAKPOINT FuncBPs;
SINGLESTEP FuncSingleStep;
EXCEPTION FuncException;
CREATEPROCESS FuncCreateProcess;
EXITPROCESS FuncExitProcess;
CREATETHREAD FuncCreateThread;
EXITTHREAD FuncExitThread;
LOADDLL FuncLoadDLL;
UNLOADDLL FuncUnLoadDLL;
OUTPUTSTRING FuncOutPutString;
RIP FuncRIP;
};
#endif
En lo que pongo arriba no me reconocería ni FuncSingleStep, ni FuncSingleStep(), ni OnSingleStep(&DebugEv) pero me pasa igual con todas las demás. He probado cosas como: Synchronize(dwContinueStatus = TDebugger::OnExitProcessDebugEvent(&DebugEv)); pero creo que esto no explota de milagro jajaja. Ya no se que probar. Última edición por aguml fecha: 27-03-2014 a las 15:01:12. |
|
#7
|
||||
|
||||
|
Se me olvidó decir que el error que da es algo asi:
[C++ Error] THiloDebugger.cpp(67): E2247 'TDebugger::OnExitProcessDebugEvent(_DEBUG_EVENT *)' is not accessible [C++ Error] THiloDebugger.cpp(67): E2283 Use . or -> to call 'TDebugger::OnExitProcessDebugEvent(_DEBUG_EVENT *)' y si pongo en el TDebugger en el private esto: friend class THiloDebugger; desaparece el primer error pero el segundo no y tampoco se si lo que hago de poner friend es algo bueno o no porque lo acabo de descubrir buscando informacion al respecto y ademas me sigue quedando el segundo error que no se como solucionarlo. |
|
#8
|
||||
|
||||
|
Con lo que pones es difícil entender lo que te pasa. Ten en cuenta que Synchronize admite como parámetro un puntero a una función miembro de tu TThread:
Código:
void __fastcall Synchronize(TThreadMethod &Method); Saludos. |
|
#9
|
||||
|
||||
|
Adjunto el proyecto y decir que el problema lo tengo en THiloDebugger y que en TDebugger puse en el private "friend class THiloDebugger" para poder acceder a las funciones private del TDebugger desde el THiloDebugger. Ya digo que estoy dando palos de ciego porque no encuentro info al respecto y lo que encuentro no estoy seguro que sea lo que necesito. Si teneis algun pdf donde se hable del manejo de hilo avanzado en C++builder para aprender y me lo pasaseis me hariais un gran favor porque en este tema estoy muy muy verde
![]() |
|
#10
|
||||
|
||||
|
Sin profuncizar mucho en tu código veo errores de bulto. Por ejemplo:
Código:
void __fastcall THiloDebugger::OnCreateThreadDebugEventThread()
{
dwContinueStatus = TDebugger::OnCreateThreadDebugEvent(&DebugEv);
}
El mismo error se repite varias veces. Piensa que necesitas hacer para diseñar las clases. Un TThread no es mas que otra clase y se rige por los mismos principios. Si vas a acceder a objetos o variables desde distintos threads al mismo tiempo ten en cuenta que escrituras simultáneas pueden corromper los hilos, de aquí que exista Synchronize. Las API de Windows suelen ser thread-safe pero la VCL no. Espero haberte orientado. Saludos. |
|
#11
|
||||
|
||||
|
pero en el loop uso Synchronize(OnCreateThreadDebugEventThread); para ejecutar el metodo que has puesto y en la clase TDebugger tengo puesto friend class THiloDebugger que se supone eso me daría acceso a las funciones privadas de la clase TDebugger desde la clase THiloDebugger ¿no? ¿entonces como lo hago?
|
|
#12
|
||||
|
||||
|
No puedes invocar una función no estática con el nombre de la clase, sino a través de un objeto, por muy amiga que sea otra clase.
Soluciona ese punto antes de buscar más errores. Saludos. |
|
#13
|
||||
|
||||
|
y entonces ¿Tengo que crear un objeto de tipo TDebugger dentro del THiloDebugger? ¿O como se hace eso?
|
|
#14
|
||||
|
||||
|
Exacto.
Saludos. |
|
#15
|
||||
|
||||
|
¿Y da igual que el TDebugger que cree en THiloDebugger no sea el que realmente está en Unit1? ¿Solo lo creo al principio del evento execute y lo elimino al final y simplemente lo uso para ejecutar sus funciones? El siguiente problema seria con los punteros a funciones que están en protected y que no son accesibles desde el objeto como por ejemplo funcexceptionbreakpoint (o algo asi era que lo digo de cabeza desde el movil) ¿Como accedo a eso desde fuera de la clase TDebugger?
|
|
#16
|
||||
|
||||
|
Cita:
Cita:
Cita:
Saludos. |
|
#17
|
||||
|
||||
|
ok amigo mil gracias, hare lo que me indicas y ya te cuento como me va.
|
|
#18
|
||||
|
||||
|
Pues acabo de probar lo siguiente.
En el constructor del hilo he puesto esto: Código:
__fastcall THiloDebugger(bool CreateSuspended, STARTUPINFO *startupInfo, TList *ListBPs, AnsiString Path, PROCESS_INFORMATION *processInfo, CONTEXT *context, DWORD *LastExcepAddress, TDebugger *Debugger); En el protected del THiloDebugger he añadido esto: Código:
TDebugger *Dbg; Código:
Dbg = Debugger; Código:
HiloDbg = new THiloDebugger(true, &si, ListaBPs, PathFile, &pi, &con, &LastExceptionAddress, this); Código:
void __fastcall THiloDebugger::OnCreateThreadDebugEventThread()
{
dwContinueStatus = Dbg->OnExitDebugEvent(&DebugEv);
}
Código:
[C++ Error] THiloDebugger.cpp(217): E2316 'OnExitDebugEvent' is not a member of 'TDebugger' |
|
#19
|
||||
|
||||
|
Vale, esto ya compila y corre y lanza el depurador y solo me falta un detalle. He creado esto:
En el protected del THiloDebugger: TEventDebugCallBack FuncEventos; En el Execute: Synchronize(GetFuncEvents); Este es el metodo: Código:
void __fastcall THiloDebugger::GetFuncEvents()
{
Dbg->GetCallBack(&FuncEventos);
}
Y aqui en el TDebugger:
// Obtener los CallBacks
void TDebugger::GetOnSystemBreakPoint(SYSTEMBREAKPOINT func){
func = FuncSystemBreakPoint;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnBPs(BREAKPOINT func){
func = FuncBPs;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnSingleStep(SINGLESTEP func){
func = FuncSingleStep;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnException(EXCEPTION func){
func = FuncException;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnCreateProcess(CREATEPROCESS func){
func = FuncCreateProcess;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnExitProcess(EXITPROCESS func){
func = FuncExitProcess;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnCreateThread(CREATETHREAD func){
func = FuncCreateThread;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnExitThread(EXITTHREAD func){
func = FuncExitThread;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnLoadDll(LOADDLL func){
func = FuncLoadDLL;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnUnLoadDll(UNLOADDLL func){
func = FuncUnLoadDLL;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnOutPutString(OUTPUTSTRING func){
func = FuncOutPutString;
}
//---------------------------------------------------------------------------
void TDebugger::GetOnRIP(RIP func){
func = FuncRIP;
}
//---------------------------------------------------------------------------
void TDebugger::GetCallBack(TEventDebugCallBack *tEstruc){
GetOnSystemBreakPoint(tEstruc->FuncSystemBreakPoint);
GetOnBPs(tEstruc->FuncBPs);
GetOnException(tEstruc->FuncException);
GetOnCreateProcess(tEstruc->FuncCreateProcess);
GetOnExitProcess(tEstruc->FuncExitProcess);
GetOnCreateThread(tEstruc->FuncCreateThread);
GetOnExitThread(tEstruc->FuncExitThread);
GetOnLoadDll(tEstruc->FuncLoadDLL);
GetOnUnLoadDll(tEstruc->FuncUnLoadDLL);
GetOnOutPutString(tEstruc->FuncOutPutString);
GetOnRIP(tEstruc->FuncRIP);
GetOnSingleStep(tEstruc->FuncSingleStep);
}
Última edición por ecfisa fecha: 29-03-2014 a las 01:26:54. Razón: Agregar etiquetas [code] |
|
#20
|
||||
|
||||
|
Hola aguml.
Por favor, no olvides usar las etiquetas [code] tu_codigo [/code] cuando pongas código C++ en el mensaje. Saludos ![]()
__________________
Daniel Didriksen Guía de estilo - Uso de las etiquetas - La otra guía de estilo .... |
![]() |
| Herramientas | Buscar en Tema |
| Desplegado | |
|
|
Temas Similares
|
||||
| Tema | Autor | Foro | Respuestas | Último mensaje |
| Problemas con hilos y remobjects Pascal Script. | J.Slann | Varios | 4 | 19-11-2011 17:35:28 |
| Problemas con acceso telefonico a redes e hilos | ospaco69 | OOP | 0 | 08-08-2007 00:02:36 |
| problemas con hilos (Thead) | jmlifi | Varios | 2 | 20-03-2007 17:56:53 |
| problemas con Hilos (Thread) | jmlifi | Varios | 2 | 26-02-2007 15:29:21 |
| Builder c++ 6 y los hilos | javikanin | C++ Builder | 1 | 26-11-2004 14:49:10 |
|