I am new to C ++ and I am designing an application that requires getting information from the internet, my problem is that if there is no internet connection, or this is slow, my application freezes for seconds. My application also has a hook to the keyboard so when my application freezes, Windows also does.
My application is for Windows only.
This is a simulation of my problem:
std::string instruction;
std::string otherValue;
int timerId;
int main(int argc, char* argv[])
{
StartKeysListener(); //Keyboard Hook
timerId = SetTimer(nullptr, 0, 5000, static_cast<TIMERPROC>(TimerCallback));
MSG msg;
while (GetMessageA(&msg, nullptr, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
VOID CALLBACK TimerCallback(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
{
DownloadInstructions();
}
std::string DownloadInstructions(std::string url)
{
std::string response = HttpRequest(url); //HttpRequest is a function that uses Windows SOCKET to send an http request
if (!response.empty())
{
instruction = response.substr(0, 5);
otherValue = response.substr(6, 15);
}
}
I have tried calling the "DownloadInstructions" function on a new thread using std::async but I do not know how to return the server response to a callback to update the "instruction" and "otherValue" variables.
How can i solve this problem? I could not find what I'm looking for on Google.
Given you are using a Win32 style message loop, the usual way to pass information back to the main thread from a worker thread is to send a message. (It doesn't look like your sample code would quite work as written as you need at least a dummy HWND though.)
Custom messages (as opposed to predefined system messages) can be defined as an offset from WM_APP, so you can do something like:
#define WM_INSTRUCTIONS_LOADING (WM_APP + 0)
#define WM_INSTRUCTIONS_READY (WM_APP + 1)
/* ... */
Then in DownloadInstructions you can notify the main thread that the download is complete by using the PostMessage API (which sends an asynchronous message) where the HWND parameter is passed in to the thread from your main loop:
PostMessage(WM_INSTRUCTIONS_READY, hwndMain, 0, 0);
Now it doesn't look like DownloadInstructions is actually running in another thread. You're using the SetTimer API which will just send a WM_TIMER message to your event loop at some point in the future. The message will still be processed in your event loop, and thus on the main thread.
You really do need to spawn a separate thread if you want it to be truly asynchronous. The mechanism for using std::async and is quite different to using CreateThread. The std::async call will spawn a thread and return you a std::future which you need to join on to get the result. This is probably not a great match for your current design. If you just spawn DownloadInstructions as a separate thread and pass it some context (at least the HWND to post back to) via the void* argument pointer, that should be sufficient to do what you describe.
Now having said all that, are you sure you want to write a C++ app using the rather old-fashioned and low-level C Win32 API? There are numerous libraries and frameworks for C++ which provide a much higher level API to do all these sorts of things more easily.
Related
As in title I want to add/remove items to a class derived from the WTL CListViewCtrl class from worker threads, but always get "Unhandled exception thrown: read access violation."
I tried Win32 API PostMessage and SendMessage but once the worker thread touches the HWND of CListViewCtrl I get the same exception.
// CListCtrl member function, calling from worker thread
HWND GetHwnd()
{
return hwndListCtrl; // exception here
}
I tried this SafeQueue but once worker thread touches the mutex or queue then exception again.
// SafeQueue is member variable in CListViewCtrl, created in GUI thread
SafeQueue<T> m_SafeQueue;
. . .
// member function in SafeQueue class, calling from worker thread
void enqueue(T t)
{
std::lock_guard<std::mutex> lock(m); // exception here
q->push(t);
}
I tried to create the mutex and queue with new and HeapAlloc/LocalAlloc but same exception again.
I tried Win32 API CreateMutex but no luck, same exception when accessing mutex handle from worker thread.
It works fine when I add items from the GUI thread.
Only way it works from worker threads if I declare HWND or mutex and queue as static/global but I would avoid this since I want to use more than one instance from this listcontrol and I prefer any more elegant way than global variable.
I want to make this class reusable since I want to use it many times with a few modifications (more columns, different colors).
I appreciate any help and idea how I can make this work.
Environment:
VS2015 Community, WTL/C++ and Win10 Pro 64bit
I found the problem that causes access violation exception:
I declared ThreadProc callback function as static member function in CListViewCtrl class.
// DO NOT USE
// in CListViewCtrl
**static** DWORD WINAPI ThreadProc(LPVOID lp)
{
. . .
}
LRESULT OnStartWorkerThread(WORD /*wNotifyCode*/, WORD /*wID*/, HWND . ..)
{
DWORD dw;
::CreateThread(NULL, 0, this->ThreadProc, NULL, 0, &dw);
}
A working solution:
class CListViewCtrl ...
{
// thread-safe queue to store listctrl items to be added later in GUI thread
SafeQueue<CListCtrlItem<nCols> > m_SafeQueue;
// thread ID of the thread in which listctrl was created, saved in OnCreate
DWORD m_dwGuiTid;
// . . .
Check if SafeAddItem function called from GUI or any other threads
BOOL InvokeRequired()
{
if (m_GuiTid == ::GetCurrentThreadId())
return false;
return true;
}
// ...
SafeAddItem member function can be called from GUI and worker threads
void SafeAddItem(CListCtrlItem<nCols> item)
{
if (!InvokeRequired())
{
// we are in GUI thread so just add listctrl item "normal" way
AddItem(item);
return;
}
// we are in other thread so enqueue listctrl item and post a message to GUI
m_SafeQueue.Enqueue(item);
::PostMessage(m_hWnd, WM_ADD_ITEM, 0, 0);
}
// . . .
Message handler of PostMessage, we are in GUI thread
LRESULT OnAddItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
CListCtrlItem<nCols> item;
while (!m_SafeQueue.Empty())
{
item = m_SafeQueue.Dequeue();
// we are in GUI thread so we can add list ctrl items normal way
AddItem(item);
}
return 1;
}
// ...
}
And now we can add listctrl items from any threads this way. I pass this pointer to ThreadProc in _beginthreadex
m_ListCtrl.SafeAddItem(item);
The question appears to be not really about UI updates from worker thread, but about proper use of worker threads per se.
There is sufficient amount of comments about dangers of doing UI updates: they are all about potential deadlock problem. Most of the updates involve sending a message, which is a blocking API call. While you do the update from worker thread and the calling thread is blocked, any attempt from the handler in the UI to synchronize or otherwise collaboratively work with the worker may result in a deadlock. The only way around this is to prepare update in the worker thread and signal the UI thread (including by posting a message instead of sending it, in terms of SendMessage, PostMessage API) to take over and complete the updates from UI thread.
Back to original problem: you seem to be having a problem with a static thread procedure. The fourth argument in the CreateThread call is:
lpParameter [in, optional]
A pointer to a variable to be passed to the thread.
You have it NULL and you are typically to use it to pass this value to your thread procedure callback. This way you can pass execution back from static function to your class instance:
DWORD CFoo::ThreadProc()
{
// ThreadProc with proper "this" initialization
// HWND h = GetHwnd()...
}
DWORD WINAPI ThreadProc(LPVOID pvParameter)
{
return ((CFoo*) pvParameter)->ThreadProc();
}
LRESULT CFoo::OnStartWorkerThread(WORD /*wNotifyCode*/, WORD /*wID*/, HWND ...)
{
DWORD dw;
::CreateThread(NULL, 0, this->ThreadProc, (LPVOID) this, 0, &dw);
}
Also note that you are not supposed to use CreateThread directly: you have _beginthreadex and AtlCreateThread (related question).
In Windows you should never directly modify a GUI control via a worker thread. In the .NET world if we want to update a control via a worker thread we have to do a platform invoke on a Delegate which basically performs a context switch.
You have a similar problem in WIN32.
There is an excellent article on this subject I will call your attention to. It also discusses various safe workarounds:
https://www.codeproject.com/Articles/552/Using-Worker-Threads
Worker threads and the GUI II: Don't touch the GUI
"That's right. A worker thread must not touch a GUI object. This means that you should not query the state of a control, add something to a list box, set the state of a control, etc.
Why?
Because you can get into a serious deadlock situation. A classic example was posted on one of the discussion boards, and it described something that had happened to me last year. The situation is this: you start a thread, and then decide to wait for the thread to complete. Meanwhile, the thread does something apparently innocuous, such as add something to a list box, or, in the example that was posted, calls FindWindow. In both cases, the process came to a screeching halt, as all threads deadlocked."
I am trying to debug a C++ MFC windows service application as we have found that in high-intensity environment there becomes a lag between the receipt and processing of third-party messages.
The service listens for received messages from a third-party system. On receiving a message, it passed the message to a dedicated processing thread which does all the processing of the command. The problem, as aforementioned, is that we are seeing a significant lag in the receipt and processing. We can see this because all messages include a sequence number. For example, our tracing reports that the main thread receives a message with sequence number 867 at 13:00:00, but we do not see the corresponding trace from the processing thread until 13:00:38 (this is a real-time system, so ideally it would be instantaneous).
I can also see in the tracing that, where on a normal system we would see a clean sequence of Receipt-Process-Receipt-Process-Recepit-Process etc..... on this log we have a block of 4 or 5 receipt messages, followed by 4 or 5 process messages, then another 4 or 5 receipt messages, and so on. Since these are running on different threads this surprises me, as I would expect to see the traces interspersed, even if delayed.
In the code, there is a message map like so:
BEGIN_MESSAGE_MAP(CProcessorThread, CWinThread)
ON_THREAD_MESSAGE(WM_MSG_RCV, OnReceive)
END_MESSAGE_MAP()
The thread class looks like this (slightly abridged):
class CProcessorThread : public CWinThread {
protected:
DECLARE_MESSAGE_MAP()
private:
CAMProcessingObject *obj;
afx_msg void OnReceive(WPARAM wParam, LPARAM lParam) {
CString* strRecData = (CString*)wParam;
CString& sTemp = *strRecData;
// Various checks and filters are done here
if (true) {
obj->ProcessMessage(sTemp);
}
delete strRecData;
}
}
Here is the method that initially receives the message from the third-party system (again, abridged):
DWORD WINAPI CAMReceiving::ThreadReceive( void * args) {
CAMObject * camObject = (CAMObject *) args;
char chTemp[500];
while(true) {
// Get the message from the socket
memset(chTemp, 0, sizeof(chTemp));
iRecvLen = camObject->objsocket.ReceiveData(chTemp, sizeof(chTemp) - 1);
CString strEventNotification = _T("");
// Do various processing to populate the strEventNotification CString and make sure we want to process this message
CString* strEvent = new CString(strEventNotification);
processorThread.PostThreadMessageA(WM_MSG_RCV,(WPARAM)strEvent,0);
continue;
}
return 1;
}
So as you may tell I didn't write this and I'm not particular familiar with the multithreading methods in C++, so my question is really is there something fundamentally wrong with this design? Or is there something I don't know that is going to cause me problems here? Thanks in advance!
I'm trying to implement device attach/detach events in my libusb-1.0 code from this example.
Here is how I'm using it:
void registerCallBack() {
int rc;
libusb_init(NULL);
rc = libusb_hotplug_register_callback(NULL, (libusb_hotplug_event) (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), LIBUSB_HOTPLUG_ENUMERATE,
0x2047, LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL,
&handle);
if (LIBUSB_SUCCESS != rc) {
printf("Error creating a hotplug callback\n");
libusb_exit(NULL);
return;
}
printf("Success registering callback\n");
}
Callback function itself:
int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event, void *user_data) {
printf("EVENT! %d\n", event);
callJava(); // call java method when event fires
return 0;
}
If I run this code and device had attached - fires event, because LIBUSB_HOTPLUG_ENUMERATE set. But if I try to attach/detach device while program running nothing happens. If I'm setting flag to 0 (not LIBUSB_HOTPLUG_ENUMERATE) then no events happens.
I have Ubuntu Linux 13.10 and libusb-1.0.16-3. Callback is registered successfully.
P.S. I use libusb in C++ library for Java program.
Thanks!
I had the same problem, and from a bit of debugging, I found that the hotplug event itself was happening and getting pushed to the event pipe. However, from looking at the libusb source, I didn't see any dedicated thread which would poll for these events. The event polling (and callback invocations) seem to be done as part of the generic transaction request handling. So I suspect (have not tested this myself though) that you have to be making control or data requests to see the hotplug callbacks.
You might try spawning a thread to call libusb_handle_events_timeout_completed() with a NULL timeout parameter, maybe once a second. That might give you what you want.
If this is correct, I wish libusb would have a flag on libusb_init() to create a thread specifically for hotplug events, without depending on control/data request calls.
I need help with C++ threading stuff, I have created a dll which has a exported function as downloadfile (to download a file from the internet). This function in turns create a thread to download a file (the function used to download a file is blocking function i.e. URLDownloadToFile that's why I put the download functionality on thread).
I want to achieve following.
my call to downloadfile function should not block the main thread.
I want to download more than one file at a time.
remember that, download functionality is in the dll created in C++ and this dll will be used in Pascal.
following is the code snippet:
struct DOWNLOADPARAM
{
HANDLE hEventStop;
TCHAR *szURL;
TCHAR *szFilePath;
};
DWORD WINAPI Transfer(void *hw)
{
Mutex mutex_;
DOWNLOADPARAM *const pDownloadParam = static_cast<DOWNLOADPARAM *>(hw);
CBSCallbackImpl bsc(NULL, pDownloadParam->hEventStop);
const HRESULT hr = ::URLDownloadToFile(NULL,pDownloadParam->szURL ,pDownloadParam->szFilePath,0,&bsc);
return 0;
}
extern "C" void __declspec(dllexport) downloadfile(TCHAR *url, TCHAR *dest)
{
Mutex mutex_;
DWORD dwThreadId;
DOWNLOADPARAM *obj = new DOWNLOADPARAM();
obj->szURL = url;
obj->szFilePath = dest;
if((hThread = CreateThread(NULL, 0, Transfer, (LPVOID)obj, 0,&dwThreadId)) != NULL)
{
}
// Following code block the thread untill finished
WaitForSingleObject(hThread, INFINITE);
TerminateThread(hThread, 0);
CloseHandle(hThread);
}
It looks like your downloadFile function is waiting for the download thread to finish before it returns, which will cause it to block just like the URLDownloadToFile function does. I would suggest that you break this apart into two operations; downloadFile should return some sort of handle or event that the calling program can use to determine whether the operation has completed, and then when it has, provide a second function that cleans up the thread and handles. That way, the calling program can continue to run and use a WaitForMultipleObjects or some other mechanism to allow it to perform its own processing while still being notified when the download has completed. My Win32 is sketchy at best, so I can't really draft up some example code, but I hope the design idea is helpful.
Calling WaitForSingleObject on thread handle immediately after launching the thread is nothing more than a synchronous/blocking call. You should defer WaitForSingleObject.
My application (the bootstrap application for an installer that I'm working on needs to launch some other applications (my installer and third party installers for my installer's prerequisites) and wait for them to complete. In order to allow the GUI to do screen updates while waiting for an app to complete, I put a message pump in the wait loop using the 'MFC-compatible' example in the Visual Studio documentation on idle loop processing as a guideline. My code (which is in a member function of a CWinApp-derived class) is as follows:
if (::CreateProcess(lpAppName, szCmdLineBuffer, NULL, NULL, TRUE, 0, NULL, NULL,
&StartupInfo, &ProcessInfo))
{
::GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
if (bWait)
while (dwExitCode == STILL_ACTIVE)
{
// In order to allow updates of the GUI to happen while we're waiting for
// the application to finish, we must run a mini message pump here to
// allow messages to go through and get processed. This message pump
// performs much like MFC's main message pump found in CWinThread::Run().
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!PumpMessage())
{
// a termination message (e.g. WM_DESTROY)
// was processed, so we need to stop waiting
dwExitCode = ERROR_CANT_WAIT;
::PostQuitMessage(0);
break;
}
}
// let MFC do its idle processing
LONG nIdle = 0;
while (OnIdle(nIdle++))
;
if (dwExitCode == STILL_ACTIVE) // was a termination message processed?
{
// no; wait for .1 second to see if the application is finished
::WaitForSingleObject(ProcessInfo.hProcess, 100);
::GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
}
}
::CloseHandle(ProcessInfo.hProcess);
::CloseHandle(ProcessInfo.hThread);
}
else
dwExitCode = ::GetLastError();
The problem that I'm having is that, at some point, this message pump seems to free up window and menu handles on the window that I have open at the time this code is run. I did a walk through in the debugger, and at no time did it ever get into the body of the if (!PumpMessage()) statement, so I don't know what's going on here to cause the window and menu handles to go south. If I don't have the message pump, everything works fine, except that the GUI can't update itself while the wait loop is running.
Does anyone have any ideas as to how to make this work? Alternatively, I'd like to launch a worker thread to launch the second app if bWait is TRUE, but I've never done anything with threads before, so I'll need some advice on how to do it without introducing synchronization issues, etc. (Code examples would be greatly appreciated in either case.)
I've also posted this question on the Microsoft forums, and thanks to the help of one Doug Harris at Microsoft, I found out my problem with my HWND and HMENU values was, indeed due to stale CWwnd* and CMenu* pointers (obtained using GetMenu() and GetDialogItem() calls. Getting the pointers again after launching the second app solved that problem. Also, he pointed me to a web site* that showed a better way of doing my loop using MsgWaitForMultipleObjects() to control it that doesn't involve the busy work of waiting a set amount of time and polling the process for an exit code.
My loop now looks like this:
if (bWait)
{
// In order to allow updates of the GUI to happen while we're
// waiting for the application to finish, we must run a message
// pump here to allow messages to go through and get processed.
LONG nIdleCount = 0;
for (;;)
{
MSG msg;
if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
PumpMessage();
else //if (!OnIdle(nIdleCount++))
{
nIdleCount = 0;
if (!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
DWORD nRes = ::MsgWaitForMultipleObjects(1, &ProcessInfo.hProcess,
FALSE, INFINITE, QS_ALLEVENTS);
if (nRes == WAIT_OBJECT_0)
break;
}
}
}
}
::GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
*That Web site, if you're curious, is: http://members.cox.net/doug_web/threads.htm
I think your problem is in WaitForSingleObject
Looking in MSDN you see this
Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and the CoInitialize function. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForSingleObject.
In my code in the message pump use use MsgWaitForMultipleObjects (doc).
With a call this call.
MsgWaitForMultipleObjects(1, &ProcessInfo.hProcess, FALSE, 100, QS_ALLEVENTS);
This should stop your problem with the resources dissapearing.
When you say that window and menu handles seem to be being freed, do you mean that you've got actual HWND and HMENU values that no longer seem to work, or have you got MFC CWnd* and CMenu* variables that fail?
If the latter, the problem is most likely that you're getting the CWnd* pointers by calling CWnd::FromHandle() (or CMenu::FromHandle()) somewhere (or calling something that calls them), and OnIdle() is discarding them.
The underlying reason is that MFC maintains a map from window (or menu, etc.) handles to CWnd* objects in the system. When CWnd::FromHandle() is called, it looks for a match in the map: if one is found, it's returned. If not, a new, temporary CWnd is created, added to the map, and returned. The idea behind OnIdle() is that when it's called all message processing is done, so OnIdle() discards any of these temporary CWnd objects that still exist. That's why the CWnd::FromHandle() documentation warns that the returned pointer may be temporary.
The "correct" solution to this is to not hang onto the CWnd* pointers returned from CWnd::FromHandle(). Given the simplicity of your application, it might be easier to just remove the call OnIdle(): this shouldn't have any negative effects on an installer.
Of course, this is all something of a guess, but it sounds plausible...
There is a Windows function called DisableProcessWindowsGhosting (see http://msdn.microsoft.com/en-us/library/ms648415(v=vs.85).aspx) that prevents Windows from 'ghosting' your window, and continue updating the window (your animation).