【问题标题】:How to invoke a method in a separate thread and use the return status如何在单独的线程中调用方法并使用返回状态
【发布时间】:2016-04-01 17:53:21
【问题描述】:

我有一个带有一种方法的类,该方法将POST 请求发送到附加文件的主机(并在发出请求后删除文件)。这是准系统代码:

using namespace Poco;
using namespace Poco::Net;

FileUploader::FileUploader(std::string aPathToFile): fPathToFile(aPathToFile)
{
}

void FileUploader::uploadFileInSeparateThread()
{
    std::thread([&](){
        this->uploadFile();
    }).detach();
}

bool FileUploader::uploadFile()
{
    try {
        const Context::Ptr context(new Context(Context::CLIENT_USE, "", "", "~/Desktop/root.pem",Context::VERIFY_ONCE));
        Poco::Net::HTTPSClientSession httpsSession(HOST, 443,context);

        HTTPRequest request(HTTPRequest::HTTP_POST, "/path/to/service?key=<name_of_file_to_be_uploaded>", HTTPMessage::HTTP_1_1);
        request.setContentType("application/x-www-form-urlencoded");
        request.setKeepAlive(true);
        HTMLForm form;
        form.setEncoding(HTMLForm::ENCODING_MULTIPART);
        form.addPart("file", new FilePartSource(fPathToFile));
        form.prepareSubmit(request);

        httpsSession.setKeepAlive(true);
        httpsSession.setTimeout(Poco::Timespan(20, 0));
        form.write(httpsSession.sendRequest(request));

        Poco::Net::HTTPResponse res;
        std::istream &is = httpsSession.receiveResponse(res);
        Poco::StreamCopier::copyStream(is, std::cout);
        qDebug() << "Message: " << is.rdbuf() << endl;
        return true;
    }
    catch (Exception &ex)
    {
        qDebug() << "Damn: " << ex.displayText().c_str() << endl;
        return false;
    }
}

如果我这样调用类:

FileUploader uploader(tempfilePath.toStdString());
uploader.uploadFile();

它工作正常,但是,当请求正在进行时,UI 被阻止。所以我决定多线程并创建一个新方法uploadFileInSeparataeThread。然后我就打电话

FileUploader *uploader = new FileUploader(tempfilePath.toStdString());
uploader->uploadFileInSeparataeThread();

这工作正常,但问题是,uploader 占用的内存永远不会被删除。所以我把它改成了一个唯一的指针:

std::unique_ptr<FileUploader> uploader(new FileUploader(tempfilePath.toStdString()));
uploader->uploadFileInSeparataeThread();

这不起作用,我收到Damn, file does not exist 错误,当我尝试在form.addPart("file", new FilePartSource(fPathToFile)); 部分中上传的文件丢失时会发生这种情况。这可能是预期的,唯一指针将在调用方法结束时超出范围。所以我尝试了这个:

FileUploader uploader(tempfilePath.toStdString());
std::thread thread([&] (FileUploader * newUploader) { newUploader->uploadFile(); }, &uploader);
thread.join();

现在可以了,但它不是多线程的,当请求进行时 UI 仍然被阻塞。

如何使其正确地成为多线程,并在成功发出POST 请求后使用来自uploadFile() 的返回值删除正在上传的临时文件?

【问题讨论】:

    标签: c++ multithreading pointers c++11 post


    【解决方案1】:

    在最后一次尝试中: 为什么在创建线程后立即调用 std::thread::join() ?它使主线程等待直到另一个线程结束。仅当 uploadFile() 方法结束时调用 join() (在代码中的其他地方,您可以检查异步调用的函数的结果是什么),否则它将等待。

    例如,您可以通过在它退出时设置一些变量或发出一些信号来了解它已退出,只是以某种方式通知 UI 它已经结束并且可以加入线程而无需强制等待。

    【讨论】:

    • Call join() only when the uploadFile() method exits, otherwise it will wait. 是什么意思?那么我该如何调用该方法
    • 创建线程的方法应该继续,然后以某种方式得知该方法已退出(设置变量或使用信号),然后调用 join()。它不能简单地在一个短代码块上完成。
    • method exists 是什么意思?我应该打电话给std::thread thread([&amp;] (FileUploader * newUploader) { newUploader-&gt;uploadFile(); }, &amp;uploader); 并继续吗?
    • 我写了方法退出,不存在方法,在 'ts' 之前没有's'。检查执行是否已退出。是的,您应该只调用该行并继续,稍后再返回加入线程,当您想阅读它的结果时最方便。
    • 如果我省略该行,应用程序就会崩溃。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 2015-01-21
    • 1970-01-01
    • 2017-07-08
    • 2023-02-01
    相关资源
    最近更新 更多