简体   繁体   中英

C++ WxWidgets: Redirecting Stdout to a wxTextCtrl across mulitple threads

My application is a multi threaded app (using wxThreads). At the moment, the main thread along with it's child worker threads are outputting various messages to Stdout (using cout).

I have a new frame/window with a wxTextCtrl, and would like to redirect all the StdOut messages in to it.

GuiLogFrame         *logframe;

logframe = new GuiLogFrame(NULL, wxID_ANY, wxEmptyString);
logframe->Show();

logredirector = new wxStreamToTextRedirector(logframe->get_log_textctrl());

This doesn't work. But if I replace the last line

wxStreamToTextRedirector redir(logframe->get_log_textctrl());

The standard out will be redirected to the logframe wxTextCtrl as long as redir is in scope... I want it to stay even when it goes out of scope.

What I want is the wxStreamToTextRedirector to stay intact the entire time the application is running... so even the new thread's cout will also redirect in to the same wxTextCtrl.

Any thoughts?

One thing that is very important to know is that GUI operations should only be done on the main thread; if you don't, it will crash or lock up when you have more than one GUI operation happening at the same time. This is definitely true under windows, but I believe it applies to all platforms. What you will need to do is post an event to the control using GetEventHandler()->AddPendingEvent. Then wx will add the event to the object's queue and when the main thread runs, it can do the GUI operation.

This might not be the exact answer to your question, but it is relevant information.

wxStreamToTextRedirector is a RAII class associating the stream with the text control in its ctor and breaking the association in its dtor. You can, of course, create it on the heap instead of using it as a local variable or even just manually do what its ctor/dtor do, ie call ostr.rdbuf(text) and restore the original value of rdbuf() at some later time.

However, as arolson101 wrote, you'd still could have a problem in your code if you allow multiple threads use the same wxTextCtrl and simple redirection won't help you with this. You would need to write your own custom streambuf -derived class which would avoid outputting the text immediately but post a message to the main GUI thread asking it to do it, which is not completely trivial.

I found one way of doing it but I didn't try it out in a multi-threaded app.

You can create a pointer to the wxStreamToTextRedirector on a constructor() using new. And then, don't forget to delete the pointer in the destructor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM