简体   繁体   English

在主线程上启动对话框等待工作线程的结果

[英]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.我有一个应用程序,它发送 HTTP 请求并处理收到的响应。 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.我希望捕获 401 响应,并在返回响应以供我的应用程序处理之前,提示用户进行身份验证。 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.根据成功,我想重试发送原始请求并返回响应,或者,如果身份验证失败,则返回原始 401 响应。

I'm using the C++ REST SDK to send HTTP requests.我正在使用 C++ REST SDK 发送 HTTP 请求。 These happen in another thread (pplx::task).这些发生在另一个线程(pplx::task)中。 I'm also using MFC modal dialog to prompt for authentication.我还使用 MFC 模式对话框来提示进行身份验证。 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.主线程等待 HTTP 请求完成。 Inside that thread, I catch a 401 and wish to launch a dialog.在该线程中,我捕获了 401 并希望启动一个对话框。 To do so, I use a boost::signal .为此,我使用了boost::signal This signal calls SendMessage to the handle I wish to display the dialog.此信号将SendMessage调用到我希望显示对话框的句柄。 After the message is processed by the MFC message loop, it will launch the dialog (on the main thread).在 MFC 消息循环处理消息后,它将启动对话框(在主线程上)。 This relies on the MFC message loop, which is blocked waiting for the HTTP request.这依赖于 MFC 消息循环,它被阻止等待 HTTP 请求。 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 .简而言之,主线程已经在等待请求完成,因此它无法运行其消息循环来接收来自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.其中 StatusCode 是 HTTP 状态代码的类型。

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).当然,这并不能解决您的 UI 线程可能等待您的工作线程完成的问题,因此您还需要某种 UI 刷新方法,该方法每 x 时间调用一次并检查所有工作线程的状态(即通过检查返回的std::future )。 You would also want to change my above example to possibly spawn a seperate thread and return an std::future in this case.你还想改变我上面的例子,在这种情况下可能会产生一个单独的线程并返回一个std::future

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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