FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
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 .... |
|
|
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 |
|