How: each doc/view in own thread (advanced)
-
Tomasz, Sorry I'wasn't complete :-) I've already updated the initial story. The input is not from user, but Trace Events from a TCP-socket. A separate thread (launched by the doc) forms a complete protocol handler and connects to a device. When a trace-event is received, a string passed to the doc which updates the view. It's also possible for the user to select a line in the view, and than press a button to add some comments. But this is rarely used, so: no user input to view. Hopes this completes the story, EiSl
I've never done MDI multi-threaded app, so can't really comment on this. There's a topic in Platform SDK titled "Using a Multithreaded Multiple Document Interface Application" (under Base Services/DLLs, Processes and Threads/Using Processes and threads). How this applies to MFC app is another story. Have fun! Tomasz Sowinski -- http://www.shooltz.com
-
Tomasz, Sorry I'wasn't complete :-) I've already updated the initial story. The input is not from user, but Trace Events from a TCP-socket. A separate thread (launched by the doc) forms a complete protocol handler and connects to a device. When a trace-event is received, a string passed to the doc which updates the view. It's also possible for the user to select a line in the view, and than press a button to add some comments. But this is rarely used, so: no user input to view. Hopes this completes the story, EiSl
I've also found MTMDI sample in MSDN. It's a MFC program that uses multiple user-interface threads. However, it's 'old-style' MFC, without the doc/view. Tomasz Sowinski -- http://www.shooltz.com
-
Hello guru's I've a interessting problem, and probably the most will say: please don't do that because of the extra headache :-D OK.. Because the fact I've a MDI application on which each doc/view can expect a lot of input. This input is no user input, but trace events read from TCP-socket. The communication handling for TCP/IP is already done it it's own thread, only passing data to the document when there's something to write. Also: I've a fast way of writing to the view, but some times the main application is very very slow in responding (moving/menu/toolbar etc) when more than 3 documents are handled with a lot of data. The problem is that all the doc/view handling is done under the hood of the applications main thread. This is the reason for wanting each doc/view in it's own thread. Now I've read sometime somewhere that someone had put each doc/view in its own thread. The question is: how to do this for a MDI application :confused: This is maybe also a very good article to store in CodeProject library. Thanks in advance.. EiSl
I would probably create a thread that handles the TCP/IP connection itself, and when it has data for displaying in a view, would send a message to the approriate view. Each view would have to register itself with the TCP/IP thread so that the thread would know who to send the data to, and the thread would have to maintain a list of views' pointers that are registered with it. I think this might give you back your interface response because the views are now only displaying data that the TCP/IP thread tells them they have.
-
I would probably create a thread that handles the TCP/IP connection itself, and when it has data for displaying in a view, would send a message to the approriate view. Each view would have to register itself with the TCP/IP thread so that the thread would know who to send the data to, and the thread would have to maintain a list of views' pointers that are registered with it. I think this might give you back your interface response because the views are now only displaying data that the TCP/IP thread tells them they have.
Hello John, Thanks for reply!! This is already how it's working now. When a new document is created (OnNewDocument), a communication thread (WinThread) is started, which is using CAsyncSockets for communications. When data has to be printed, it is passed to the document. But... When I've have more than 3 documents active, and they generating quite a lot data, the main app starts become less responsive since all the documents/view updates are done under the hood of the main application thread. That was the reason for asking a thread handling doc/view archtecture. EiSl
-
Hello John, Thanks for reply!! This is already how it's working now. When a new document is created (OnNewDocument), a communication thread (WinThread) is started, which is using CAsyncSockets for communications. When data has to be printed, it is passed to the document. But... When I've have more than 3 documents active, and they generating quite a lot data, the main app starts become less responsive since all the documents/view updates are done under the hood of the main application thread. That was the reason for asking a thread handling doc/view archtecture. EiSl
-
Hello guru's I've a interessting problem, and probably the most will say: please don't do that because of the extra headache :-D OK.. Because the fact I've a MDI application on which each doc/view can expect a lot of input. This input is no user input, but trace events read from TCP-socket. The communication handling for TCP/IP is already done it it's own thread, only passing data to the document when there's something to write. Also: I've a fast way of writing to the view, but some times the main application is very very slow in responding (moving/menu/toolbar etc) when more than 3 documents are handled with a lot of data. The problem is that all the doc/view handling is done under the hood of the applications main thread. This is the reason for wanting each doc/view in it's own thread. Now I've read sometime somewhere that someone had put each doc/view in its own thread. The question is: how to do this for a MDI application :confused: This is maybe also a very good article to store in CodeProject library. Thanks in advance.. EiSl
I don't think that a thread per doc/view is a good approach: there are a lot of complications, and it doesn't change the fact that only one thread can update the GUI at a time (the GDI calls are serialized). A much better approach, which I have used successfully in a couple of commercial applications, is to have one worker thread per doc, with the original GUI thread handling all the views. The worker threads can update each documents contents to reflect the input recieved via TCP/IP independently. You can run into some problems invoking window related functions from a worker thread because of the need to link C++ objects like CWnds with the associated Windows HWND (look up handle maps in the VC++ docs if you want the messy details). As long as the worker threads stick to updating the data in the CDocument derived class, you won't have problems. You may have to use critical sections or some other form of synchronization to stop the GUI thread from reading partially updated document contents though. I get around the handle map problem by defining a user message UM_UPDATE_VIEWS. The worker threads POST (not send) this message to the main window after changing the document contents. The main GUI thread processes this message, by calling CDocument::UpdateAllViews() for the CDocument derived object passed as a pointer in the LPARAM. This way UpdateAllViews() gets invoked by the main GUI thread, so there is no problem with handle maps. Stephen C. Steel Kerr Vayne Systems Ltd.
-
Hello John, Does this really matters?!? Ok in case of a CFormView yes it matters. In my case we're talking about a read-only CEditView, but maybe this is changed to a CListView. Sincerly, EiSl
You'd probably be better off with a CFormview with a CListBox in it. I'd be willing to bet that (with the CEditView) you are simply adding the newest message to the existing contents of the edit control. At first, performance is pretty good, but the longer the program runs, the worse less responsive the program gets. If you change to a list box, you have better control over how much data is contained in the control (you could limit it to say 1000 lines). With an edit control, you have to call SetWindowText with a string that is larger each time. This takes a lot of processing time (a lot more time than adding a single string to a list box). I would advise against using a list control unless you need multiple columns for some reason. A list box would be a better choice.
-
You'd probably be better off with a CFormview with a CListBox in it. I'd be willing to bet that (with the CEditView) you are simply adding the newest message to the existing contents of the edit control. At first, performance is pretty good, but the longer the program runs, the worse less responsive the program gets. If you change to a list box, you have better control over how much data is contained in the control (you could limit it to say 1000 lines). With an edit control, you have to call SetWindowText with a string that is larger each time. This takes a lot of processing time (a lot more time than adding a single string to a list box). I would advise against using a list control unless you need multiple columns for some reason. A list box would be a better choice.
Thanks for your answer! Most the time you read answer like: "better do this way" without a clear explaination why to do so. I've never thougth about the combination of CFormView with ListBox, because I was only looking to derivation of the View. Since it only accepts xxxView I was thinking about the ClistView or CEditView and have chosen for the editview. When everything is working fine I will take a look for changing that part, since it's quite easy to change. Happy programming! Eize
-
Thanks for your answer! Most the time you read answer like: "better do this way" without a clear explaination why to do so. I've never thougth about the combination of CFormView with ListBox, because I was only looking to derivation of the View. Since it only accepts xxxView I was thinking about the ClistView or CEditView and have chosen for the editview. When everything is working fine I will take a look for changing that part, since it's quite easy to change. Happy programming! Eize
I had the same problem in a previous project that I inherited. We were storing messages coming across a network in an edit control. These messages could be anywhere from 2-64k in length, and that we got approximately 150 messages per minute, and we were simply adding them to the edit control with no thought of the size of the string *in* the edit control. Performance slowed to such a point that the CPU utilization was pegged at 100% and we got so far behind in the message queue that the only recourse was to do a hardware reset. The really embarassing part was that our app was the only one running. LOL Anyway, we needed to have the edit control, so we changed the code buy only storing only the previous message in the edit control. Performance improved dramatically, and we regained keyboard control of the system. Good luck on your project. :-)