I have been using Casablanca in Win32 projects (WTL). I am not an expert in either Win32 or Casablanca, but here's my two cents in case it helps.
I believe the problem you are seeing is related to threading. The key point here is that Casablanca calls (or is very likely to call) handler methods like handle_post on threads other than the main (UI) thread.
In all UI frameworks I can think of (including MFC) it is not allowed to interact with the UI directly from background threads. In particular in Win32:
- Controls have what is called 'thread affinity', which in short means that the system stores some or all of their windows-related data in thread local storage, so directly accessing the controls from background threads simply doesn't work as expected. This
is not what is happening in your case though (SendMessage is used under the covers, see below), nor would it cause hangs.
- Call like m_ListBox.AddString are implemented using SendMessage() calls in frameworks like WTL and MFC. SendMessage is a blocking function and it is a bad idea to be issuing calls to it from background threads. This is WTL's implementation (MFC's will be
// manipulating listbox items
int AddString(LPCTSTR lpszItem)
return (int)::SendMessage(m_hWnd, LB_ADDSTRING, 0, (LPARAM)lpszItem);
The key for your program to function correctly is to replace the SendMessage() call with PostMessage(). For example
- You could directly call PostMessage([hwnd of target control], LB_ADDSTRING,...) but this has problems related to the lifetime of the string parameter.
- You can define custom window messages for communicating with the UI of your application (sort of an interface) and use PostMessage to send them to your UI thread.
I prefer the second method (this is what I have been doing and I have seen no problems) because it leads to cleaner structure of your application. You can define wrapper methods (members of your main window) that internally call PostMessage.
Of course you need to be careful when calling PostMessage with parameters such as strings. Exactly because you message is being pushed in a queue (that is, it is not processed synchronously) all parameters need to be valid not only at the point where PostMessage
is called but also at the point where the message is actually processed (via the message map of the window). If you follow the wrapper methods approach, you can new up a string on the call site and delete it on the receiving end or use WM_COPYDATA (see here
). I find the first approach simpler and this is what I have been using.
This is one of the cases we still need to explicitly use new and delete in new C++ applications, but then again Win32 is a pretty old framework. Of course with a bit of work you can wrap up everything pretty nicely.
Note that this is not a Casablanca-specific issue. You are likely to run into similar problems if you directly use PPL (or pplx that comes with Casablanca) or std::thread or _beginthread().