Access a socket that has been passed to thread - c++

I am new to MFC's CWinThread and CAsyncSocket, and trying to learn them myself with dialog based application.
Here is what I want to do: make a server/multi-client model: when the number clients connect to server, the server will make threads according to the number of clients and passes the socket connecting to the thread. I have refereed this article to do the passing: https://support.microsoft.com/en-us/kb/175668 .
I have successfully make thread on every connection, but...
My question is: Can I from the main windows(GUI) re-access all sockets that have been passed to threads to send(broadcast) data to all the clients?
This is how I do the passing:
On server side:
void CMyServerDlg::OnAccept(){
CConnectSoc temp_soc;
m_Listener.Accept(temp_soc);
CSocketThread *pThr = (CSocketThread*)AfxBeginThread(
RUNTIME_CLASS(CSocketThread),
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
pThr->threadHandleSocket = temp_soc.Detach();
pThr->ResumeThread();
}
Note: m_Listener is the object of the class that derived from CAsyncSocket and CSocketThread is derived from CWinThread.
Inside the thread header, I added 2 lines:
Public:
CConnectSoc threadSocket;
SOCKET threadHandleSocket;
Inside the thread class .cpp:
BOOL CSocketThread::InitInstance(){
threadSocket.Attach(threadHandleSocket);
return TRUE;
}
Can someone tell me what to do next to send data to those socket?

After some research, I finally think I can answer my own question, thanks for your help; but please fix me, if there is a better solution or mine is not a good practice.
MY SOLUTION:
The key word here is PostMessage() and PostThreadMessage(). We must make the communication between the GUI and the Threads. However, the problem is the thread cannot call PostMessage() which is a member function of CWnd to send message to the GUI (I have no idea why not). So I need a pointer in the thread class to point to the CWnd from the GUI:
In header of the thread class:
public:
CWnd *wParrent;
Then at the stage of creating thread, I just have to add 1 line:
void CMyServerDlg::OnAccept(){
CConnectSoc temp_soc;
m_Listener.Accept(temp_soc);
CSocketThread *pThr = (CSocketThread*)AfxBeginThread(
RUNTIME_CLASS(CSocketThread),
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED);
pThr->wParrent = this; //<== this line
pThr->threadHandleSocket = temp_soc.Detach();
pThr->ResumeThread();
}
By doing this, I can now post message from the thread to give the GUI my thread's ID.
In the thread .cpp:
BOOL CSocketThread::InitInstance(){
threadSocket.Attach(threadHandleSocket);
wParrent->PostMessage(THREAD_STARTED, 0, (LPARAM)m_nThreadID);
return TRUE;
}
Then at GUI: we handle message THREAD_STARTED with a function to store m_nThreadID for future use:
Somewhere in Dlg header:
CDWordArray m_threadIDs;
Dlg .cpp
LRESULT CMyServer3Dlg::OnThreadStart(WPARAM, LPARAM lParam){
DWORD ThreadID = (DWORD)lParam;
m_threadIDs.Add(ThreadID);
return 0;
}
When sending data to all clients, use PostThreadMessage() in a loop through m_ThreadIDs:
for (int i =0; i<m_threadIDs.GetCount(); ++i){
PostThreadMessage(m_threadIDs[i],SEND_DATA,(WPARAM)bufferSize,(LPARAM)socketBuffer);
}
Handle SEND_DATA message in the thread with a function to do the sending:
In thread .cpp:
void CSocketThread::SendDataFunc(WPARAM wParam, LPARAM lParam){
ASSERT(threadSocket != NULL);
if(threadSocket == NULL)
{
return;
}
else
{
char *socketBuffer = (char*)lParam;
int bufferSize = (int)wParam;
send(threadSocket, socketBuffer, bufferSize, 0);
}
That's what I have done, and no problem so far....

Related

Win32, MFC: Ending threads

I have a DLL which has a CWinThread based class called CWork.
I create it using AfxBeginThread.
In this class I defined a procedure that will loop infinetly and perform a certain task. This procedure will be used as a thread by itself. I create it also using AfxBeginThread.
Now, when my DLL exits, I'd like to end the thread. This is because I have a crash on exit, and I am affraid that is the reason.
In addition, there is
Pseudo Code example:
class Cmain
Cmain::Cmain(){
pMyThread = AfxBeginThread(CWork - a CWinThread based Class);
}
UINT HandleNextVTSConnectionCommandProc(LPVOID pParam);
class CWork
CWork:CWork(){
AfxBeginThread(HandleNextVTSConnectionCommandProc, this);
}
UINT HandleNextVTSConnectionCommandProc(LPVOID pParam){
while(true){
dosomething();
sleep(2000);
}
}
My question is, what is the correct way of ending those 2 threads?
Thank you!
In general the correct way to end a thread is to ask it to finish and then wait for it to do so. So on Windows you might signal an event to ask the thread to finish up then wait on the thread HANDLE. Forcefully terminating a thread is almost always a misguided idea which will come back to haunt you.
Create an event calling CreateEvent that is initially non-signaled. When your application terminates, signal this event (SetEvent) and wait for the thread to terminate (WaitForSingleObject on the thread handle).
Inside your thread function HandleNextVTSConnectionCommandProc replace your while(true) loop with
while(WaitForSingleObject(hEvent, 0) != WAIT_OBJECT_0)
Doing the above allows you to signal the thread to terminate from your application. The thread terminates, when it returns from its thread proc.
Set a flag instead of using while(true) to tell your thread when it should end. You could also use an event.
You should also wait for your thread to be complete before you exit, so you should use (in the main code, once you signal the thread to end):
WaitForSingleObject(thread_handle)
Something like this should get you started:
HANDLE g_hThreadExitRequest = NULL;
UINT __cdecl ThreadFunction(LPVOID pParam)
{
AllocConsole();
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
for (int i=1; true; ++i)
{
CStringA count;
count.Format("%d\n", i);
WriteFile(hCon, (LPCSTR)count, count.GetLength(), NULL, NULL);
if (WaitForSingleObject(g_hThreadExitRequest, 1000) == WAIT_OBJECT_0)
break;
}
// We can do any thread specific cleanup here.
FreeConsole();
return 0;
}
void Go()
{
// Create the event we use the request the thread exit.
g_hThreadExitRequest = CreateEvent(
NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
TRUE, // BOOL bManualReset
FALSE, // BOOL bInitialState
NULL // LPCTSTR lpName
);
// We create the thread suspended so we can mess with the returned CWinThread without
// MFC auto deleting it when the thread finishes.
CWinThread *pThread = AfxBeginThread(
&ThreadFunction, // AFX_THREADPROC pfnThreadProc
NULL, // LPVOID pParam
THREAD_PRIORITY_NORMAL, // int nPriority
0, // UINT nStackSize
CREATE_SUSPENDED , // DWORD dwCreateFlags
NULL // LPSECURITY_ATTRIBUTES lpSecurityAttrs
);
// Turn off MFC's auto delete "feature".
pThread->m_bAutoDelete = FALSE;
// Start the thread running.
pThread->ResumeThread();
// Wait 30 seconds.
Sleep(30*1000);
// Signal the thread to exit and wait for it to do so.
SetEvent(g_hThreadExitRequest);
WaitForSingleObject(pThread->m_hThread, INFINITE);
// Delete the CWinTread object since we turned off auto delete.
delete pThread;
// We're finished with the event.
CloseHandle(g_hThreadExitRequest);
g_hThreadExitRequest = NULL;
}

How to define CWinThread in MFC?

I have set an int variable for the "EditBox" control in c++/mfc. now I want to change its value in a thread.
I define a thread like the bellow :
CWinThread *pThread();
UINT FunctionThread(CthDlg& d)
{
DWORD result = 0;
int i = 0;
while (1)
{
if (i == 5000) i = 0;
d.m_text1 = i;
i++;
d.UpdateData(FALSE);
}
return result;
}
void CthDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
pThread = AfxBeginThread(FunctionThread, THREAD_PRIORITY_NORMAL);
}
Where's the Problem?
You should run your code in debug mode and under the debugger, then you would see that you get an assertion.
The problem is that MFC only allows access to a window from the thread that created the window. In your case that means that the main thread can access the windows, but the worker thread can not. UpdateData is accessing the windows, so this does not work in a worker thread.
So what you need to do is signal from the worker thread to the main thread that a new value is available and shall be displayed. For that signaling you can post a window message to the dialog window (PostMessage). Be sure not to use SendMessage because this will block until the message is received. You might run into a dead lock if the main thread is waiting for the worker thread and the worker thread is waiting for the main thread in SendMessage. When the main thread receives the message it can update the window control.
BTW, your code is not valid. AfxBeginThread requires a AFX_THREADPROC which is declared as UINT __cdecl MyControllingFunction(LPVOID pParam);. You need to change your thread function to
UINT __cdecl FunctionThread(LPVOID pParam)
{
CthDlg& d = *reinterpret_cast<CthDlg*>(pParam);

My 'show progress thread' doesn't run when it counts

I have a thread that does lengthy processing. While I am waiting for the thread to finish, I kick start another 'show progress' thread which simply toggles a bitmap back and forth to show program is crunching on data. To my surprise this approached didn't work at all.
My 'show progerss' thread simply stop updating (=running) when the main activity starts and it starts updating when that activity ends. This is nearly the oppose of what I want! Should I expect this behavior because of the WaitForSingleOBjectwhich is in wait state for most of the time and wakes up briefly?
// This is the main thread that does the actual work
CWinThread* thread = AfxBeginThread(threadDoWork, this, THREAD_PRIORITY_LOWEST, 0, CREATE_SUSPENDED );
thread->m_bAutoDelete = FALSE;
thread->ResumeThread();
// before I start to wait on the above thread, I start this thread which will toggle image to show application is processing
AfxBeginThread(ProgressUpdateThread, &thread_struct_param, THREAD_PRIORITY_NORMAL, 0 );
// wait for the main thread now.
DWORD dwWaitResult = WaitForSingleObject( thread->m_hThread, INFINITE );
DWORD exitCode;
::GetExitCodeThread( thread->m_hThread, &exitCode );
delete thread;
// This thread toggles image to show activity
UINT ProgressUpdateThread(LPVOID param)
{
CEvent * exitEvent = ((mystruct *)param)->exitEvent;
MyView *view ((mystruct *)param)->view;
int picture = 0;
do
{
waitResult = WaitForSingleObject( exitEvent->m_hObject, 100);
if (waitResult == WAIT_TIMEOUT)
{
picture = toggle ? 1: 0;
// invert
toggle = !toggle;
View->Notify( UPDATE_IMAGE, picture );
}
else if (waitResult == WAIT_OBJECT_0)
{
return TRUE;
}
}
while( 1);
}
Another consideration in my solution is that I would like to not touch the actual 'DoWork' thread code and that's also why I am using separate thread to update GUI. Can I make this approach work? Is the only way to update GUI reliable is to update it from the actual 'DoWork thread itself?
I do want to clarify that my 'Show progress' thread does the job perfectly if the application is idle, but if I launch the worker thread operation (in lower thread priority), the update gui thread simply stops running and resume only when the worker finishes.
I am using Windows 7.
Your design is all wrong and over-complicated for what you are attempting. Try something more like this simpler solution:
bool toggle = false;
VOID CALLBACK updateProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
int picture = toggle ? 1: 0;
toggle = !toggle;
View->Notify( UPDATE_IMAGE, picture );
}
CWinThread* thread = AfxBeginThread(threadDoWork, this, THREAD_PRIORITY_LOWEST, 0, CREATE_SUSPENDED );
thread->m_bAutoDelete = FALSE;
thread->ResumeThread();
UINT_PTR updateTimer = SetTimer(NULL, 0, 100, updateProc);
do
{
DWORD dwWaitResult = MsgWaitForMultipleObjects(1, &(thread->m_hThread), FALSE, INFINITE, QS_ALLINPUT );
if (dwWaitResult == WAIT_OBJECT_0)
break;
if (dwWaitResult == (WAIT_OBJECT_0+1))
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
while (true);
KillTimer(NULL, updateTimer);
DWORD exitCode;
::GetExitCodeThread( thread->m_hThread, &exitCode );
delete thread;
If you do not want to use a standalone procedure for the timer, you can adjust the parameters of SetTimer() to have it post WM_TIMER messages to an HWND of your choosing instead, and then do the UI updates in that window's message procedure as needed. You would still need the message loop to pump the timer messages, though.
The alternative is to simply not do any waiting at all. Once you start the worker thread, move on to other things, and let the worker thread notify the main UI thread when it is done with its work.
Remy Lebeau pointed out correctly that my main GUI thread was actually waiting on the worker thread. Now since my worker gui-update thread was (obviously) calling gui function, it was in turn blocked on main GUI thread. I realized even SetWindowText() from a third thread will put that thread in wait if the main GUI thread is in wait or blocked state.
I don't like to use PeekandPump() mechanism, I thought it was a bad design smell. It was originally used in early windows (before win95 I think) which were not truly multitasking. To the best of my knowledge this should not be used now.
My solution was to put the whole code that I posted in OP in a new thread. So my button click in gui creates this threat and returns immediately. This master worker thread can now wait on other threads and my GUI will never block. When it gets completed, it post a message to the parent window to notify it. The bitmap is now changed perfectly using a separate gui-update thread when the application is processing in another thread.

Sending a message to a window that belongs to another thread. Possible Deadlock?

I think i am ruining in to a deadlock, have been searching for the solution over hours. Any suggestions?
What i am trying to do is: ater startGame button click, create thread that send request to the server and then gets the answer, after the answer the thread must send a message to Initialize game window to the main proc...
Message Proc that belongs to WinMain:
LRESULT CALLBACK WndProc(HWND myWindow, UINT messg, WPARAM wParam, LPARAM lParam)
{
switch (messg) {
case WM_STARTGAME:
DestroyWindow(hStartGameButton);
DestroyWindow(hHistoryButton);
InitGameWindow(myWindow);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_STARTGAME_BUTTON:
{
parametros param;
param.myWindow = myWindow;
start_game = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadStartGame, (LPVOID)&myWindow, 0, NULL);
}
}
}
And this is the thread:
DWORD WINAPI ThreadStartGame(LPVOID param){
HWND w = (HWND)param;
DWORD n;
BOOL ret;
mensagem resposta;
mensagem msg;
msg.tipo = COMECAR_JOGO;
msg.verifica = true;
if (!WriteFile(hPipe, &msg, (DWORD)sizeof(mensagem), &n, NULL)) {return 0;}
ret = ReadFile(hPipeN, &resposta, (DWORD)sizeof(mensagem), &n, NULL);
if (!ret || !n) {
return false;
}
PostMessage(w, WM_STARTGAME, NULL, NULL); // <- THIS GETS EXECUTED BUT NOTHINK HAPPENS AFTER
return 0;
}
I don't think there is any deadlock here.
start_game = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadStartGame, (LPVOID)&myWindow, 0, NULL);
This line passes the address of the HWND to the thread (&myWindow)
HWND w = (HWND)param;
This line uses the adress itself as HWND and the SendMessage sends the message to this address which is not a HWND.
Try modifying to
start_game = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadStartGame, (LPVOID)myWindow, 0, NULL);
W/o even looking at the code, I can tell you right away: do not use SendMessage between threads. I recommend reading Psychic debugging: The first step in diagnosing a deadlock is a simple matter of following the money and Preventing Hangs in Windows Applications:
Use asynchronous window message APIs in your UI thread, especially by replacing SendMessage with one of its non-blocking peers: PostMessage, SendNotifyMessage, or SendMessageCallback
...
Any blocking call that crosses thread boundaries has synchronization properties that can result in a deadlock. The calling thread performs an operation with 'acquire' semantics and cannot unblock until the target thread 'releases' that call. Quite a few User32 functions (for example SendMessage), as well as many blocking COM calls fall into this category.
For starters, you're unlikely supposed to do that in the first place. Quoting MSDN:
A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multithreaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.
Second, your thread can be worker or UI thread, from the first type you must not call most of the window related functions, as it has no message pump. DestroyWindow is such. (So many times I tried to use MessageBox despite my own comment a few lines upper telling it's forbidden in that function ;).
From worker threads the usual method is to use PostThreadMessage and react on the UI thread. (If you have multiple UI threads, I don't know the rules, was never brave enough for that.)

Properly closing window created on a separate thread using ATL

I have a multithreaded application and on certain threads, I'm creating windows using ATL's CWindowImpl<>. I have a static method that I'm using as the thread procedure. I need to create a window on the thread, because I need some of my communication with the thread to be synchronous, and PostThreadMessage() is expressly asynchronous. When my window receives the WM_DESTROY message (handler defined by the MESSAGE_HANDLER macro), it calls PostQuitMessage(), as shown in this method:
LRESULT MyATLWindowClass::OnDestroy(UINT uMsg,
WPARAM wParam,
LPARAM lParam,
BOOL& bHandled) {
::PostQuitMessage(0);
return 0;
}
I'm using a custom message to the thread using PostThreadMessage() to indicate to the thread that it's time to terminate itself. Handling that custom message, I call the CWindowImpl::DestroyWindow() method, which does appear to properly destroy the window, as my OnDestroy message handler is getting called. However, it doesn't appear that the owning thread ever receives a WM_QUIT message for processing. Included below is a simplified version of my thread procedure.
unsigned int WINAPI MyATLWindowClass::ThreadProc(LPVOID lpParameter) {
// Initialize COM on the thread
::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
// Create the window using ATL
MyATLWindowClass new_window;
HWND session_window_handle = new_window.Create(
/* HWND hWndParent */ HWND_MESSAGE,
/* _U_RECT rect */ CWindow::rcDefault,
/* LPCTSTR szWindowName */ NULL,
/* DWORD dwStyle */ NULL,
/* DWORD dwExStyle */ NULL,
/* _U_MENUorID MenuOrID */ 0U,
/* LPVOID lpCreateParam */ NULL);
// Initialize the message pump on the thread.
MSG msg;
::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
// Run the message loop
BOOL get_message_return_value;
while ((get_message_return_value = ::GetMessage(&msg, NULL, 0, 0)) != 0) {
if (get_message_return_value == -1) {
// GetMessage handling logic taken from MSDN documentation
break;
} else {
if (msg.message == WD_SIGNAL_THREAD_SHUTDOWN) {
// Requested thread shutdown, so destroy the window
new_window.DestroyWindow();
} else if (msg.message == WM_QUIT) {
// Process the quit message and exit the message loop
// to terminate the thread
break;
} else {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
}
// Uninitialize COM on the thread before exiting
::CoUninitialize();
return 0;
}
Note that it doesn't seem to matter if I call DestroyWindow() or if I send a WM_CLOSE message to the window. The thread's message pump is not receiving WM_QUIT in either case. Should the owning thread's message pump be receiving such a message? Where is my misunderstanding about how the thread's message pump and the window's message pump interact? Or what am I missing about how ATL's window classes create and manage windows?
GetMessage() never returns WM_QUIT. That message forces it to return 0 instead, designed to terminate your message loop.
Beware of the considerable hazards of using PostThreadMessage(). It should never be used on a thread that also displays windows, like the one you are using. The issue is that it doesn't take a HWND argument. So only your message loop can see the message, it won't be delivered to any window with DispatchMessage(). This goes wrong when a modal message loop is entered, the kind that are outside of your control. Like the modal loop that makes MessageBox work. Or the one that Windows uses to allow the user to resize a window. Or the one that DialogBox() uses. Etcetera. Always use PostMessage(), use your own message number.
Some late additional thoughts. You could probably safely terminate your message loop as soon as you have discovered WD_SIGNAL_THREAD_SHUTDOWN:
if (msg.message == WD_SIGNAL_THREAD_SHUTDOWN) {
// Requested thread shutdown, so destroy the window
new_window.DestroyWindow();
break; // exit the message loop
}
DestroyWindow is a synchronous call, the window will be fully destroyed before it returns and you can exit the loop. So, posting WM_QUIT would be redundant.
Also, you could use message-only window, if the windows is invisible and its only purpose is to process messages.