C ++ WxWidgets:跨越多个线程将Stdout重定向到wxTextCtrl

时间:2022-02-25 19:34:02

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).

我的应用程序是一个多线程应用程序(使用wxThreads)。此时,主线程及其子工作线程正在向Stdout输出各种消息(使用cout)。

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

我有一个带有wxTextCtrl的新框架/窗口,并希望将所有StdOut消息重定向到它。

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.

只要redir在范围内,标准输出将被重定向到logframe wxTextCtrl ...我希望它在超出范围时保持不变。

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.

我想要的是wxStreamToTextRedirector在应用程序运行的整个时间内保持完整......所以即使新线程的cout也会重定向到相同的wxTextCtrl。

Any thoughts?

3 个解决方案

#1


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.

要知道的一件事是GUI操作应该只在主线程上完成;如果不这样做,当同时发生多个GUI操作时,它将崩溃或锁定。在Windows下这绝对是正确的,但我相信它适用于所有平台。您需要做的是使用GetEventHandler() - > AddPendingEvent将事件发布到控件。然后wx会将事件添加到对象的队列中,当主线程运行时,它可以执行GUI操作。

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

这可能不是您问题的确切答案,但它是相关信息。

#2


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.

您可以使用new在构造函数()上创建指向wxStreamToTextRedirector的指针。然后,不要忘记删除析构函数中的指针。

#3


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, i.e. call ostr.rdbuf(text) and restore the original value of rdbuf() at some later time.

wxStreamToTextRedirector是一个RAII类,它将流与其ctor中的文本控件相关联,并在其dtor中断开关联。当然,您可以在堆上创建它,而不是将其用作本地变量,甚至只需手动执行其ctor / dtor所做的操作,即调用ostr.rdbuf(text)并将rdbuf()的原始值恢复为某些值。晚点。

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.

但是,正如arolson101写的那样,如果允许多个线程使用相同的wxTextCtrl,那么你的代码中仍然会遇到问题,简单的重定向对你没有帮助。您需要编写自己的自定义streambuf派生类,这样可以避免立即输出文本,但会将消息发布到主GUI线程,要求它执行此操作,这并非完全无关紧要。

#1


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.

要知道的一件事是GUI操作应该只在主线程上完成;如果不这样做,当同时发生多个GUI操作时,它将崩溃或锁定。在Windows下这绝对是正确的,但我相信它适用于所有平台。您需要做的是使用GetEventHandler() - > AddPendingEvent将事件发布到控件。然后wx会将事件添加到对象的队列中,当主线程运行时,它可以执行GUI操作。

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

这可能不是您问题的确切答案,但它是相关信息。

#2


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.

您可以使用new在构造函数()上创建指向wxStreamToTextRedirector的指针。然后,不要忘记删除析构函数中的指针。

#3


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, i.e. call ostr.rdbuf(text) and restore the original value of rdbuf() at some later time.

wxStreamToTextRedirector是一个RAII类,它将流与其ctor中的文本控件相关联,并在其dtor中断开关联。当然,您可以在堆上创建它,而不是将其用作本地变量,甚至只需手动执行其ctor / dtor所做的操作,即调用ostr.rdbuf(text)并将rdbuf()的原始值恢复为某些值。晚点。

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.

但是,正如arolson101写的那样,如果允许多个线程使用相同的wxTextCtrl,那么你的代码中仍然会遇到问题,简单的重定向对你没有帮助。您需要编写自己的自定义streambuf派生类,这样可以避免立即输出文本,但会将消息发布到主GUI线程,要求它执行此操作,这并非完全无关紧要。