Autor
|
Tema: ¿Qué esta mal con esta creacion de HILO (Thread)? (Leído 3,256 veces)
|
yovaninu
Desconectado
Mensajes: 349
|
Buenas a todos, googleando, encontre este ejemplo de creacion de un HILO y modificandolo un poco llama a una funcion y ésta a su vez ejecuta un bucle de 1000 iteraciones, al hacerlo correr en VS2005, la ventana tipica aparece pero al parecer la aplicacion o no crea el hilo o no detecta cuando éste ha terminado, les dejo el codigo: #define _WIN32_WINNT 0x0500 #define _CRT_SECURE_NO_DEPRECATE #include <windows.h> #include <stdlib.h> #include <string.h> #include <tchar.h> #include <string> #include <atlstr.h> /*Declaraciones para nuestro hilo*/ DWORD WINAPI ThreadFunc( LPVOID ); UINT TerminoProceso; static DWORD dwThreadId; static HANDLE hThread=NULL; DWORD cod; char cade[20]; MSG messages; // Global variables int a; int b; int c; CString t; // El nombre de la clase de la ventana principal static TCHAR szWindowClass[] = _T("VentanaWin32"); // El texto que aparece en la ventana principal static TCHAR szTitle[] = _T("Una ventana tipica de win32"); HINSTANCE hInst; //variable global para //El propósito de esta función es procesar cualquier mensaje que nuestra aplicación reciba del sistema operativo LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); /************************************************************/ /************************FUNCION PRINCIPAL*******************/ /************************************************************/ int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { /*Creamos el hilo*/ hThread = CreateThread( NULL, // sin atributos de seguridad 0, // Tamaño de la pila por defecto ThreadFunc, // Funcion del hilo hInstance, // argumento de la funcion del hilo (pasado por referencia) 0, // creacion de banderas por defecto &dwThreadId); // puntero a la variable donde se guardara el id del hilo //Esta estructura contiene información sobre la ventana, tal como el icono de la aplicación, //el color de fondo de la ventana, el nombre que aparece en la barra de título, //el nombre de la función de procedimiento de ventana, etc. WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ASTERISK)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ASTERISK)); if (!RegisterClassEx(&wcex)){ MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); return 1; } hInst = hInstance; HWND hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 200, NULL, NULL, hInstance, NULL ); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } /*Funcion que sera ejecutada por el HILO*/ DWORD WINAPI ThreadFunc( LPVOID lpParam ) { int i,j=0,l=0; HWND *mhwnd,mHwnd; mhwnd=(HWND*)lpParam; mHwnd=*mhwnd; for(i=0;i<10000;i++) { j++; } PostMessage(mHwnd,TerminoProceso,0,0); //cuando finalice... return (DWORD)l; } //Callback de los mensajes... LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; TCHAR greeting[] = _T("Probando Hilos..."); /*para reconocer cuando termina el HILO y asi poder destruirlo*/ if(message==TerminoProceso) { cod=GetExitCodeThread(hThread,&cod); while(cod==STILL_ACTIVE) { GetExitCodeThread(hThread,&cod); } a=(int)cod; itoa(a,cade,10); MessageBoxW(hWnd,L"dddd",L"info",MB_ICONINFORMATION); CloseHandle(hThread); hThread=NULL; return 0; } //procesamos los mensajes principales switch (message) { case WM_CREATE: /*registramos un nuestro mensaje personalizado para detectar el momento en que el hilo termina*/ TerminoProceso=RegisterWindowMessage("ProcesoFin"); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); /*un mensaje comun en la ventana*/ TextOut(hdc,5, 5,greeting, _tcslen(greeting)); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); break; } return 0; }
Pienso que estoy pasando mal algun parametro a CreateThread, alguna sugerencia.???
|
|
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.969
Israel nunca torturó niños, ni lo volverá a hacer.
|
El hilo es creado, el problema esta en el parametro. En hInstance no esta el HWND sino la cabecera del ejecutable (MZ). Por logica el hilo lo tenes que crear DESPUES de crear la ventana si le queres pasar el HWND de la misma ... Simple solucion: En WinMain moves la llamada a CreateThread a justo despues de Y en lugar de pasar hInstance como parametro al hilo pasas hWnd. En ThreadFunc: HWND mHwnd = (HWND)lpParam;
|
|
« Última modificación: 17 Septiembre 2011, 22:28 pm por Eternal Idol »
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
yovaninu
Desconectado
Mensajes: 349
|
En efecto, funciona. Gracias Eternal Idol, supongo que al implementar otras cosas de esta forma me surgiran otros problemas, espero contra siempre con vuestra ayuda. Dejo el code completo funcional para aquel que se inicie en esto de los HIlos aunque he modificado la funcion que ejecuta el hilo para que demore exagerando un poco. La pregunta es como haria para mostrar en el cuadro de texto el valor de la variable 'LINC' que se supone se incrementa mientras los bucles del hilo se ejecutan, la finalidad era mostrar el valor final de 'LINC' cuando el hilo termina en un MessageBox, por ahora solo muestra 1. A ver si ponemos 100% funcional el ejemplo. #define _WIN32_WINNT 0x0500 #define _CRT_SECURE_NO_DEPRECATE #include <windows.h> #include <stdlib.h> #include <string.h> #include <tchar.h> #include <string> #include <atlstr.h> /*Declaraciones para nuestro hilo*/ DWORD WINAPI ThreadFunc( LPVOID ); UINT TerminoProceso; static DWORD dwThreadId; static HANDLE hThread=NULL; DWORD cod; char cade[10]; MSG messages; // Global variables char a; int LINC=0; // El nombre de la clase de la ventana principal static TCHAR szWindowClass[] = _T("VentanaWin32"); // El texto que aparece en la ventana principal static TCHAR szTitle[] = _T("Una ventana tipica de win32"); HINSTANCE hInst; //variable global para //El propósito de esta función es procesar cualquier mensaje que nuestra aplicación reciba del sistema operativo LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); /************************************************************/ /************************FUNCION PRINCIPAL*******************/ /************************************************************/ int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { //Esta estructura contiene información sobre la ventana, tal como el icono de la aplicación, //el color de fondo de la ventana, el nombre que aparece en la barra de título, //el nombre de la función de procedimiento de ventana, etc. WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ASTERISK)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ASTERISK)); if (!RegisterClassEx(&wcex)){ MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); return 1; } hInst = hInstance; HWND hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 200, NULL, NULL, hInstance, NULL ); ShowWindow(hWnd,nCmdShow); UpdateWindow(hWnd); /*Creamos el hilo*/ hThread = CreateThread( NULL, // sin atributos de seguridad 0, // Tamaño de la pila por defecto ThreadFunc, // Funcion del hilo hWnd, // argumento de la funcion del hilo (pasado por referencia) 0, // creacion de banderas por defecto &dwThreadId); // puntero a la variable donde se guardara el id del hilo MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } /*Funcion que sera ejecutada por el HILO*/ DWORD WINAPI ThreadFunc( LPVOID lpParam ) { int i,j=0,k,s; HWND mHwnd = (HWND)lpParam; for(i=0;i<1000;i++) for(k=0;k<4000;k++) for(s=0;s<90;s++) LINC++; /*Variable que se incrementa*/ PostMessage(mHwnd,TerminoProceso,0,0); return (DWORD)LINC; /*Devolvemos la variable cuando finaliza este hilo*/ } //Callback de los mensajes... LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; TCHAR greeting[] = _T("Probando Hilos..."); /*para reconocer cuando termina el HILO y asi poder destruirlo*/ if(message==TerminoProceso) { cod=GetExitCodeThread(hThread,&cod); while(cod==STILL_ACTIVE) { GetExitCodeThread(hThread,&cod); } a=(int)cod; itoa(a,cade,20); /*Aqui deberiamos mostrar el ultimo valor de la variable 'LINC'*/ MessageBoxW(hWnd,(LPWSTR)cade,L"El hilo a Finalizado",MB_ICONINFORMATION); CloseHandle(hThread); hThread=NULL; return 0; } //procesamos los mensajes principales switch (message) { case WM_CREATE: /*registramos un nuestro mensaje personalizado para detectar el momento en que el hilo termina*/ TerminoProceso=RegisterWindowMessage("ProcesoFin"); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TextOut(hdc,5, 5,greeting, _tcslen(greeting)); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); break; } return 0; }
|
|
|
En línea
|
|
|
|
Eternal Idol
Kernel coder
Moderador
Desconectado
Mensajes: 5.969
Israel nunca torturó niños, ni lo volverá a hacer.
|
No tiene ningun sentido usar mas variables globales que LINC, no tenes que asignarle el resultado de GetExitCodeThread a cod (es un bool y el while no se ejecuta nunca de esa manera) y no podes llamar a MessageBoxW con una cadena ASCII por mas que le hagas un casting a wide: DWORD cod; GetExitCodeThread(hThread,&cod); while (cod == STILL_ACTIVE) { GetExitCodeThread(hThread,&cod); } char cade[20]; itoa(cod,cade,10); /*Aqui deberiamos mostrar el ultimo valor de la variable 'LINC'*/ MessageBoxA(hWnd, cade, "El hilo ha Finalizado", MB_ICONINFORMATION);
PD. Si alguna vez queres acceder a una variable global desde mas de un hilo tenes que usar sincronizacion.
|
|
|
En línea
|
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste. Juan Domingo Perón
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
servidor ocupado: no se puede completar esta acción porque el programa está ocup
Windows
|
baldomero
|
8
|
31,585
|
19 Marzo 2015, 18:05 pm
por eltecnico07
|
|
|
[DUDA] Error '3704' La operacion no esta permitida si el objeta esta cerrado
Programación Visual Basic
|
omarzito22
|
0
|
8,076
|
9 Octubre 2010, 18:03 pm
por omarzito22
|
|
|
No se si esta consulta va en este hilo
Hardware
|
ElQueNoSabeNada
|
7
|
3,965
|
17 Agosto 2012, 15:03 pm
por ElQueNoSabeNada
|
|
|
Un hilo de Reddit está siendo adaptado al cine por un guionista de Hollywood
Noticias
|
wolfbcn
|
1
|
2,420
|
18 Enero 2013, 18:22 pm
por crazykenny
|
|
|
creacion de thread en linux desde c
GNU/Linux
|
JAHVEM13
|
0
|
1,775
|
15 Octubre 2013, 23:06 pm
por JAHVEM13
|
|