Launch Async Thread via Button Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
cneng3
Knows some wx things
Knows some wx things
Posts: 26
Joined: Sat Apr 28, 2018 7:43 pm

Launch Async Thread via Button

Post by cneng3 »

Hey all,

I'm trying to launch an async thread that does some time-consuming task.

Code: Select all

void MyClass::OnButton_1Click(wxCommandEvent& event)
{
    auto fut = std::async(std::launch::async, [this]{ /// code});
    event.Skip()
}
I have 2 problems here. First, this piece of code still freezes the UI, means that the newly launched thread is not really async, it still pauses the UI thread. Second, how to update UI thread, such as popping a dialog box says the task is done, after the background thread finishes.
I thought this code would sort work because after the line where it creates the future object, it should launch a thread in the background and UI thread will keep executing. However, the program doesn't work as I planned. Could someone tell me where I did wrong? Thx!
User avatar
eranon
Can't get richer than this
Can't get richer than this
Posts: 867
Joined: Sun May 13, 2012 11:42 pm
Location: France
Contact:

Re: Launch Async Thread via Button

Post by eranon »

Hello, If you want to implement a worker thread the wxWidgets way, you have to derive wxThread (your class providing its own Entry() method mainly), then this class will send a custom event (so, you have to define this event and add an handler for it in your main thread) to the main thread when something will be ready (job done!). Also, remember to never use any GUI related functions in this worker thread. You have a thread-oriented example among the wxWidgets samples. You can also google "wxthread"... After study, if you have a specific difficulty on a specific point in your own code, it will be easier to help you...
[Ind. dev. - wxWidgets 3.0/3.1 under "Win 7 64-bit, TDM64-GCC" + "OS X 10.9, LLVM Clang"]
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Launch Async Thread via Button

Post by doublemax »

From http://en.cppreference.com/w/cpp/thread/async
If the std::future obtained from std::async is not moved from or bound to a reference, the destructor of the std::future will block at the end of the full expression until the asynchronous operation completes, essentially making code such as the following synchronous:

Code: Select all

std::async(std::launch::async, []{ f(); }); // temporary's dtor waits for f()
std::async(std::launch::async, []{ g(); }); // does not start until f() completes
(note that the destructors of std::futures obtained by means other than a call to std::async never block)
Use the source, Luke!
cneng3
Knows some wx things
Knows some wx things
Posts: 26
Joined: Sat Apr 28, 2018 7:43 pm

Re: Launch Async Thread via Button

Post by cneng3 »

I don't think this caused my problem since I have store the std::future object obtained by std::async in a variable. The dtor shouldn't block the GUI thread's execution
doublemax wrote:From http://en.cppreference.com/w/cpp/thread/async
If the std::future obtained from std::async is not moved from or bound to a reference, the destructor of the std::future will block at the end of the full expression until the asynchronous operation completes, essentially making code such as the following synchronous:

Code: Select all

std::async(std::launch::async, []{ f(); }); // temporary's dtor waits for f()
std::async(std::launch::async, []{ g(); }); // does not start until f() completes
(note that the destructors of std::futures obtained by means other than a call to std::async never block)
cneng3
Knows some wx things
Knows some wx things
Posts: 26
Joined: Sat Apr 28, 2018 7:43 pm

Re: Launch Async Thread via Button

Post by cneng3 »

I'm very aware of the existence of wxThread class, however, I think it's a lot of overhead to create a separated class just to launch a thread and this thread just calls a single function. Do you think it's possible for me to achieve what I want withbonly std::async or std::thread?
eranon wrote:Hello, If you want to implement a worker thread the wxWidgets way, you have to derive wxThread (your class providing its own Entry() method mainly), then this class will send a custom event (so, you have to define this event and add an handler for it in your main thread) to the main thread when something will be ready (job done!). Also, remember to never use any GUI related functions in this worker thread. You have a thread-oriented example among the wxWidgets samples. You can also google "wxthread"... After study, if you have a specific difficulty on a specific point in your own code, it will be easier to help you...
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7458
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Launch Async Thread via Button

Post by ONEEYEMAN »

Hi,
cneng3 wrote: I don't think this caused my problem since I have store the std::future object obtained by std::async in a variable. The dtor shouldn't block the GUI thread's execution
Can you post the complete code - how did you store the pointer and where?

Thank you.
User avatar
eranon
Can't get richer than this
Can't get richer than this
Posts: 867
Joined: Sun May 13, 2012 11:42 pm
Location: France
Contact:

Re: Launch Async Thread via Button

Post by eranon »

cneng3 wrote:I'm very aware of the existence of wxThread class, however, I think it's a lot of overhead to create a separated class just to launch a thread and this thread just calls a single function. Do you think it's possible for me to achieve what I want withbonly std::async or std::thread?
I don't know, I rely on wxWidgets everywhere I can... And if I have something to improve it's always from concrete profiling; not from my assumptions. You think it's an overhead, but in real facts, you don't know. If you want to be sure, produce two samples (one through wxThread and one through std::async/thread) and profile both. Then, after this concrete test stage, you'll have a real reason to prefer a way or another.
[Ind. dev. - wxWidgets 3.0/3.1 under "Win 7 64-bit, TDM64-GCC" + "OS X 10.9, LLVM Clang"]
cneng3
Knows some wx things
Knows some wx things
Posts: 26
Joined: Sat Apr 28, 2018 7:43 pm

Re: Launch Async Thread via Button

Post by cneng3 »

I'm afraid that I can't post the complete source code since what I'm working on doesn't mean to be an open source project. I'm sorry. I can only write some simple code to demonstrate what I'm trying to do here.
And I don't quite understand your questions. I'm not using any pointers in std::async, except "this".
ONEEYEMAN wrote:Hi,
cneng3 wrote: I don't think this caused my problem since I have store the std::future object obtained by std::async in a variable. The dtor shouldn't block the GUI thread's execution
Can you post the complete code - how did you store the pointer and where?

Thank you.
User avatar
eranon
Can't get richer than this
Can't get richer than this
Posts: 867
Joined: Sun May 13, 2012 11:42 pm
Location: France
Contact:

Re: Launch Async Thread via Button

Post by eranon »

cneng3 wrote:I'm afraid that I can't post the complete source code since what I'm working on doesn't mean to be an open source project.
I talked about sample, not your entire project. Here, a lot of us are working on closed source, but it doesn't mean we don't show some code when required ; and when you ask for help, it's required.
[Ind. dev. - wxWidgets 3.0/3.1 under "Win 7 64-bit, TDM64-GCC" + "OS X 10.9, LLVM Clang"]
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Launch Async Thread via Button

Post by doublemax »

Code: Select all

void MyClass::OnButton_1Click(wxCommandEvent& event)
{
    auto fut = std::async(std::launch::async, [this]{ /// code});
    event.Skip()
}
Everything i find about this topic says that the "fut" destructor will block until the code is finished. Try assigning the result to a member variable and check if it changes the behavior.
Use the source, Luke!
cneng3
Knows some wx things
Knows some wx things
Posts: 26
Joined: Sat Apr 28, 2018 7:43 pm

Re: Launch Async Thread via Button

Post by cneng3 »

Wow it actually worked! I knew the code could actually launch async threads but had no idea why they were still "synchronous" when I used std::launch::async. Thank you!
doublemax wrote:

Code: Select all

void MyClass::OnButton_1Click(wxCommandEvent& event)
{
    auto fut = std::async(std::launch::async, [this]{ /// code});
    event.Skip()
}
Everything i find about this topic says that the "fut" destructor will block until the code is finished. Try assigning the result to a member variable and check if it changes the behavior.
Post Reply