![]() |
problema con thread
amigos una ves mas recurro a su ayuda, lo que sucede es que dentro de mi programa se lleva acabo un retardo necesario para el funcionamiento del mismo, pero bueno este retardo que en si esta da do por una funcion del tipo
WaitForSingleObject detiene el resto de mi programa impidiendo que en este se lleven acabo otras funciones como oprimir un boton, el retardo es de unos 3 segundos, aca mi pregunta: como puedo evitar que este retardo dentro de el hilo detenga la ejecucion del resto de mi programa, de antemano muchas gracias?:confused: |
¿Estás obligado a usar WaitForSingleObject?, Existen otras formas de esperar a que termine un thread sin un bloqueo total de la aplicación.
Código:
// Declaras una variable de la clase bool Terminado, porque Terminated no es accesible desde fuera. Le asignas true en el thread al terminar.Saludos. |
Esa funcion la estas llamando desde un hilo o la usas en medio de tu aplicacion? Yo creo que no estas empleando hilos, y lo que dice escafandra es inconsistente por el concepto de los hilos. Cuando creas un hilo, en su funcion Execute() debes hacer algo asi:
Código:
void __fastcall TUnThread::Execute()Una nota ultima, el Application->ProcessMessages(); no es una mala idea pero de todas maneras no es una buena practica. Lo mas recomendable (aunque un poco complicado) es emplear hilos. Espero que te ayude Luiggi |
luiggixD, Perdona pero no me parece inconsistente, de hecho lo utilizo para esperar a la terminación de un thread en un programa que estoy escribiendo y que debe esperar, solo que no uso WaitForSingleObject, que congela toda la aplicación, sino el sistema que he descrito. Es posible que no me explicase bien, de forma que amplio un poco tu código de ejemplo añadiendo mi idea:
Código:
void __fastcall TUnThread::Execute()Código:
Form1::Funcion(){Saludos. |
En teoria el hilo no debe detener a la aplicacion. Si dentro del hilo realizas operaciones que interactuan con el Form o con cualquier otra parte de tu aplicacion, lo mejor seria sincronizar(funcion_form), donde funcion_form es una funcion que defines dentro del hilo que encapsula todas las interacciones con el form, ahora puedes elaborar muchas mas funciones. El hilo no deberia detener al programa, y asi no empleas el Application->ProcessMessages();
me deje entender?? me parece raro que se congele tu programa empleando hilos XD! quizas en tu misma aplicacion estes haciendo algo que la retrase |
muchas gracias a ambos por su ayuda, pero creo que yo me he equivocado ya que siento que no me he explicado bien, cuando le doy "imag->Resume();"
el hilo inicia, en ese momento mi hilo llama a una funcion invocada desde una dll (de la cual tengo el codigo fuente) esta funcion esta definida en el programa principal y no en el hilo, la funcion usa un WaitForSingleObject, esta funcio detiene por completo mi programa tanto el hilo "que es el que se debe detener por este tiempo", y el resto de la aplicacion en la cual no puede ni presionar otro boton. espero les sea mas claro, gracias amigos.:D |
podrias detener el hilo con la funcion Suspend() y luego le haces un Reume()
|
Cita:
El hilo debe interactuar con Synchronize con el form. Pero imagina que parte del código no puede seguir sin conocer un resultado. Y que ese resultado va a tardar en saberse. Entonces te puede interesar colocar en un hilo el código que sabes que va a tardar y por lo tanto semibloquear la aplicación unos segundos. ¿Y la espera...? Si la espera la haces con WaitForSingleObject, entonces es un desastre... Con el sistema que propongo, la aplicación no espera nada, los eventos siguen ocurriendo, lo único que espera es el código que mantiene el bucle descrito. Te preguntarás: Si al final usas ProcessMessages(), ¿Entonces porqué programar un hilo?. Pues para que las llamadas a ProcessMessages() no se interrumpan por la tarea que más tarde, por ejemplo una conexión a internet o llamada a procesos API que obligan a esperar... Como pulpin ha hecho la pregunta, he dado por hecho que estaba ante una situación como la que describo y por eso le propongo esto. Evidentemente es sólo para estos casos especiales de describo. De todas formas pulpin ha resuelto su problema. Saludos.;) |
no porque mi hilo esta en ejecucion y la funcion necesariamente se tiene que detener durante ese tiempo mientras le llegan otros datos, cuando espera el rsto de mi programa deberia estar en funcionamiento normal.
cuando recibe los datos el hilo sigue su funcionamiento normalmente. eje: Form { codigo form incluyendo botones y demas; invoco la funcion recibo datos(desde una dll); } inicio de hebra { recibo datos(estafuncion contiene el wait.....); //aqui es donde se para //todo mi programa por 3 segundos, cada que pasa por este sitio, y solo //deberia parar en el hilo. } espero ser mas ilustrativo:p |
El problema es que WaitForSingleObject para todo. Lo que no entiendo es si la llamas tú o si lo hace la dll. Si la llamas tú, sabrás cual es el proceso que esperas que termine... No debería llamarse desde un hilo pues deja de tener sentido ese hilo.
Si puedes: Código:
función(...)¿Te sirve? Saludos. |
pues escafranda desafortunadamente no puedo escaparme del waitforsingleobject ya que este esta dentro del codigo de la dll y es necesario .
:( |
Mala cosa. Revisa esto, aunque posiblemente lo has hecho.
Dices que tienes el código fuente de esa dll.... Podrias modificarla y recompilarla. Sólo es una idea aunque posiblemente la peor. Saludos. EDITO: Mira WaitForMultipleObjects también por si te sirve. |
igualmente gracias por tu ayuda escafranda, voy a ver como puedo resolver este inconveniente, espero no se me salga de las manos.
post: tu siempre salvandome de tanto enredo, ya te debo como 5.:p |
aun sigo en problemas
bueno estube investigando, sobre waitformultipleobjects, y segun lo que lei si utilizo esta funcion puedo evitar que los demas hilos se interrunmpan, estoy en lo correcto o no puedo usarlo para este motivo, espero tu opinion?;)
por ultimo alguna idea de como hacer el cambio. |
Bueno, por lo que dices, te debes haber decidido por recompilar la dll. En principio lo fácil sería hacer ese cambio que apuntas. Cambiar la función
DWORD WINAPI WaitForSingleObject( __in HANDLE hHandle, __in DWORD dwMilliseconds );[FONT=verdana,geneva,lucida,'lucida grande',arial,helvetica,sans-serif] por: [/font]DWORD WINAPI WaitForMultipleObjects( __in DWORD nCount, __in const HANDLE* lpHandles, __in BOOL bWaitAll, __in DWORD dwMilliseconds ); La diferencia es que el hilo lo debes pasar como una matriz de hilos, es decir un puntero al handle en cuestión. En nCount pones 1 (un sólo hilo). En este caso bWaitAll no tiene mucho sentido, colócalo en true. Por último aquí tienes más información: WaitForSingleObject y WaitForMultipleObjects Saludos. |
estube pensando en otra solucion sin modificar el dll.
bueno segun lei en internet es posible evitar este inconveniente si dentro del hilo seda el waitforobject, el codigo de la funcion principal se seguiria procesando normalmente. pero al ensayar tube un inconveniente que no se como buscar, mi programa es: Form1-> "el cual es el que inicia normalmente, donde se cargan todas las funciones donde se inicia todo mi programa y el qye normalmente esta pendiente de los botonoes y demas metodos." Form2->" en el cual se desprende una pequeña ventana en la cual puedes editar una imagen que se encuantra en el Form1 para luego imprimirla." Form3->" y el ultimo y mas doloroso, un objeto thread en el cual lo que hago es llamar metodo void Del form1 , en la cual se lleva acabo una graficacion y recepcion de datos de un microcontrolador" lo que quiero es hacer la recepcion de datos dentro del hilo ya que la recepcion es la que detiene el proceso esta contiene el waitforobject, luego de recibir los datos me voy para el void del form1 y grafico y luego vuelvo para la siguiente recepcion. sera que asi me funciona? lo que no me ha dejado llevar acabo mi plan es uqe la funcion que recibe los datos esta definida de la siguiente forma: DWORD SendReceivePacket(BYTE *SendData, DWORD SendLength, BYTE *ReceiveData,DWORD *ReceiveLength, UINT SendDelay, UINT ReceiveDelay); // definida en el form1 mi preguntas es como puedo llamar esta funcion desde la hebra "form3"? gracias, espero tu opinion.:) |
Bueno... Para usar elementos de la VCL en un thread, deba asegurarse la seguridad, valga la redundancia. Debes revisar el método Synchronize. Y creo que debes hacerlo así pues quieres llamas a una función de una clase de Form1 a la que no pertenece tu thread. Cualquier modificación en objetos VCL debe llevarse a cabo de esta manera.
En la ayuda de Builder tienes un ejemplo demostrativo de como usar Synchronize. Saludos. |
bueno depronto creo que me e vuelto a enredar un poco, lo que necesito desde mi thread (hilo.cpp) es llamar a una funcion que se encuentra en el proceso principal (osciloscopio.cpp) una funcion definida como DWORD (as,jj,sfd,kjh);
normalmente puedo llamar funciones y demas asi: Form1->Button1->click(); pero esta funcion no la he podido llamar, la verdad e tratado de muchas formas de hacerlo pero no he hallado la forma, y en internet no logro allar informacion de este tipo de funcion. espero ser mas claro.:rolleyes: |
Pues como te indiqué, con el método Synchronize:
Código:
#include "Unit1.h" // la del Form1...Saludos. |
bueno, la cosa no va como quiero, la verdad sigue igual, he incorporado dos soluciones siguiendo tus pasos y el consejo visto en la red pero o lo he hecho mal o no funciona.
en la primera llamo la funcion desde el hilo, y todo bien hasta que mi funcion invoca la funcion de la dll y esta a su ves procesa el waitforobject, donde todo se detiene. en la segunda, hago una "transaccion" defino las funciones en el hilo, y para usarlas en el form1, las llamo form3->sendreceivetpacket();, en cierta forma evito que el hilo procese algo en el form1(creo), pero aun asi el proceso se relentiza cuando en la dll se da el waitforobject. la verdad ya no se que hacer, voy a tratar pasando todo lo que tiene que ver con la comunicacion (inicializacion de dll, inicio de comunicacion definiendo endpoints,etc) a ver si asi no se detiene. y si no tendre que dejar de esa forma mi tesis. bueno espero que puedas darme algun consejo u idea que tengas, y antes de que se me olvide disculpa por tanto enredo en algunos casos, ya que soy 90% empirico en c++. gracias.:( |
Pienso que el problema sigue estando en esa dll. Si llamas a funciones de esa dll desde tu hilo, y se encuentra con un WaitForSingleObject... Se detiene.
Sigo pensando que si tienes las fuentes de la dll, la modifiques y recompiles... Quizas puedas probar una solución un poco menos drástica. Sobrecarga sólo la función de la dll que te da problemas. Para eso, crea un archivo cpp con la función y la incluyes en el archivo cpp donde la uses o en la del form1. En esa sobrecarga puedes intentar el cambio WaitForSingleObject por WaitForMultipleObjects tal como comentábamos hace unos posts. O utilizando la primera técnica que te comenté para esperar (pero entonces deberás crear otro hilo mas que se llame desde tu hilo...) Código:
# include "archivo.cpp"Por último decirte que esto que te pasa no tiene que ver con Builder ni C++ sino con Windows, WaitForSingleObject es de la API de Windows. |
creo que eso de modificar a waitformultipleobjects, es mas compleajo porque cuando trate de hacerlo me salia un error que no entendia, ya que lo hice a la rapida, "cambio, pongo los parametros basicos y listo", pues no entiendo eso, pero bueno, en este momento estoy tratando de llevar al hilo todo lo de la comunicacion, pero tengo un problema creo que no es dificil pero no se que hacer, desde el hilo estoy llamando objetos ->
Form1->RadioButton2->Checkked=true; todo compila bien pero cuando el sistema trata de procesar esa linea para el proceso y muestra un error de "violacion de acceso a memoria en form1.cpp....." cuando llamo desde form1 que es donde incluyo= #include "hilo.cpp" tod me sale bien pero a la inversa no. que puedo hacer? y por ultimo luego de ensayar de esta forma me pondre a hacer lo que me dices de crear otro hilo y cargarlo desde mi primer hilo a ver que sucede. Espero no perder la esperanza ya que es lo ultimo que me falta para terminar. |
Insisto que para llamar desde el hilo a funciones o usar propiedades de Form1, debes utilizar Synchronize.
Código:
|
si ya estoy usando la funcion de sincronizacion, exactamente igual que en el post, dentro de la funcion que estoy sincronizando, invoco objetos del form1 pero me salen los errores que te mencio, si incluyo form1.cpp, en hilo.cpp me sale un error de doble declaracion de parametros.
|
No debes incluir Form1.cpp sino la cabecera.
#include Form1.h Saludos. |
esta ya la tengo incluida,la cabecera del form1.h y aun asi sale ese error.
como te digo compila bien pero cuando ejecuto y entra a procesar = (ejemplo) Form1->RadioButton2->Checked=true; me detiene el proceso y sale un error de acceso invalida a memoria o algo asi. |
Pues ese error de violación de acceso de memoria se debe a un puntero que apunta a un espacio de memoria que no pertenece a tu proceso.
Revisa tus punteros. ¿Existen todos?. ¿Alguno es nulo?. No tiene sentido el error en Form1->RadioButton2->Checked=true; pues tanto Form1 como el hilo pertenecen a tu aplicación y por tanto es un espacio de memoria al que tienes permiso de acceso. Form1 es un puntero, como RadioButton2. Revisa con el debuguer paso a paso. ¿Que valor tienen?. En ocasiones, fallos cometidos con puteros dan la cara mas tarde en zonas de código donde no deberían presentarse. Se debe a una corrupción de memoria. Esa dll que usas.. ¿No estará inyectando código en otro proceso?. En fin, el error no está donde te parece a primera vista... Saludos. |
Por fin una solucion parcial
Bueno, despues de mucho pelear encontre la solucion a mi problema y realmente es sencilla, retomando: mi problema se presentaba al inicio de la comunicacion durante 2 seg paraba mi programa por completo al llamar una funcion que en su interior contenia waitforsubject.
Realmente conocia el tiempo que se demoraba mi problema, lo que hice fue insertar un sleep antes de que se ejecutara el synchronize de mi hilo, el sleep seria controlado por una variable la cual me permitia cambiar este molesto inconveniente cuando fuese necesario. Bueno creo que fue una solucion util, algo que conocemos pero que ami no se ubiese ocurrido en su momento. Gracias por todo tu apoyo Escafranda. Eres (el)(la) mejor. Cuidate.:p |
Bueno, soy el.
Saludos. |
| La franja horaria es GMT +2. Ahora son las 11:17:06. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi