简体   繁体   中英

Launch dialog on main thread waiting for result of worker thread

I have an app which sends off HTTP requests and processes the received response. The main thread is blocked until a response comes back, else we couldn't process the data. To send these requests, the user must be authenticated. I wish to catch a 401 response and before returning the response for processing by my app, prompt the user for authentication. Depending on the success, I want to retry to send the original request and return that response instead, or, if authentication fails, return the original 401 response.

I'm using the C++ REST SDK to send HTTP requests. These happen in another thread (pplx::task). I'm also using MFC modal dialog to prompt for authentication. Some of you may see the deadlock that occurs. If not, let me explain more.

The main thread waits for the HTTP request to complete. Inside that thread, I catch a 401 and wish to launch a dialog. To do so, I use a boost::signal . This signal calls SendMessage to the handle I wish to display the dialog. After the message is processed by the MFC message loop, it will launch the dialog (on the main thread). This relies on the MFC message loop, which is blocked waiting for the HTTP request. In short, the main thread is already waiting for the request to finish so it can't run its message loop to receive the call from SendMessage .

Main thread is waiting on worker thread. Worker thread needs to launch a dialog on main thread before it can continue. Deadlock. Does anyone have any clever solutions for ways around this?

I think the simplist solution here is to redesign the way you are handling your threads.

I suggest that instead of having a single thread for requests, you spawn a new thread for each request and then have it return the status code (no matter what it is), you can then handle any logic for retrying with authentication within your main thread (ie display an authentication dialog, then respawn the authentication thread with the credentials).

This also allows you to encapsulate your request handler better, which is a big plus. In order to properly encapsulate this logic (so you dont have to check every request) you should define some kind of request handler (either a class or a function). For example

StatusCode make_reqeust(...) {
  // Deal with the logic on authentication here
}

Where StatusCode is a type for a HTTP status code.

Of course this doesnt solve the issue of your UI thread potentially waiting for your worker thread to finish, so you also need some kind of UI refresh method which is called every x amount of time and which checks the status of all the worker threads (ie by checking the returned std::future 's). You would also want to change my above example to possibly spawn a seperate thread and return an std::future in this case.

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