c++ - 使用 std::async 引用对象

标签 c++

我在 Visual Studio 2012 中有一个小解决方案。该解决方案由两个项目组成(Scanner 和 TestApp),Scanner 是一个 dll,TestApp 是一个使用 dll 的小应用程序。 我希望 dll 中的函数在线程中运行,并通过队列将其结果报告给 TestApp。 为了测试这一点,我编写了一个最小的应用程序,但根据我启动线程的方式,我得到了不同的结果,我想了解原因。

Scanner.h 文件如下所示:

#pragma once

#include <iostream>
#include <string>
#include <stdint.h>
#include <atomic>
#include <future>
#include <thread>

#include "version.h"
#include "threadsafe_queue.h"
#include "capture_data.h"
#include "process_data.h"


#ifdef SCANNER_EXPORTS  
#define SCANNER_API __declspec(dllexport)   
#else  
#define SCANNER_API __declspec(dllimport)   
#endif  

class Scanner
{
public:
    static SCANNER_API void run();  
    static SCANNER_API void stop(); 
};

扫描仪.cpp:

#include "stdafx.h"
#include "Scanner.h"

std::vector<std::future<int>> my_futures;

void Scanner::run()
{
    CaptureData capture_data(1234);
    auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
    my_futures.push_back(std::move(t));
}

void Scanner::stop()
{
    for(int n=0; n<my_futures.size(); n++) {
    auto e = std::move(my_futures.back());
    e.get();
    my_futures.pop_back();
    }
}

CaptureData 类在 capture_data.h 和 capture_data.cpp 中定义。

capture_data.h:

#pragma once

#include <atomic>
#include <thread>
#include "iq_data.h"
#include "threadsafe_queue.h"

class CaptureData
{
public:
    CaptureData(double freq_start);
    void configure();
    void get_data();
private:
    double m_test;
};

capture_data.cpp

#include "stdafx.h"
#include "capture_data.h"
#include "Scanner.h"

ThreadsafeQueue<int> g_queue_1;
SCANNER_API ThreadsafeQueue<int> g_queue_2;


CaptureData::CaptureData(double test) 
    : m_test(test) {}

void CaptureData::get_data() 
{
    cout << "1: " << m_test << std::endl;
    Sleep(5000);
    cout << "2: " << m_test << std::endl;   
    g_queue_2.push(3);
    cout << "Capture has now pushed data" << std::endl;
}

最后是TestApp.cpp:

#include "stdafx.h"
#include "tchar.h"
#include <stdint.h>
#include <string>
#include "Scanner.h"


SCANNER_API extern ThreadsafeQueue<int> g_queue_2;

int _tmain(int argc, _TCHAR* argv[])
{
    Scanner scanner;
    scanner.run();
    cout << "TestApp waiting for data..." << std::endl;
    int data;
    g_queue_2.wait_and_pop(data);
    cout << "TestApp got data: " << data << std::endl;
    scanner.stop();

    return 0;
}

在 Scanner.cpp 中,我尝试以两种不同的方式启动线程,第一种方式:

auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);

第二种方法是引用对象“capture_data”:

auto t = std::async(std::launch::async, &CaptureData::get_data, &capture_data);

第一种方法似乎可以正常工作,因为我希望应用程序能够工作,并且我在终端中得到以下打印输出:

TestApp waiting for data... 
1: 1234 
2: 1234 
Capture has now pushed data 
TestApp got data: 3 
Press any key to continue...

如果我使用第二种方式,我得到:

TestApp waiting for data... 
1: 6.95166e-310
2: 6.95166e-310 
Capture has now pushed data 
TestApp got data: 3 
Press any key to continue...

所以,我不明白的是为什么变量“m_test”在第二种情况下会变得困惑。 如果有人能阐明这一点,我将非常感激。

/M

最佳答案

在下面的代码中:

void Scanner::run()
{
    CaptureData capture_data(1234);
    auto t = std::async(std::launch::async, &CaptureData::get_data, capture_data);
    my_futures.push_back(std::move(t));

}

capture_data 是一个局部变量,它超出范围并在函数返回时被销毁。如果将指向该变量的指针传递给异步,该指针将成为悬空指针,导致未定义的行为。如果您按值传递它,则不会发生这种情况,就像在上面的代码片段中所做的那样。

关于c++ - 使用 std::async 引用对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47155293/

相关文章:

c++ - Android NDK 中的未知类型名称错误

c++ - 为什么我不能在下面的代码中使用 `pos_type` 返回类型?

c++ - fflush(stdin) 的替代方案?

c++ - std::vector push_back 是瓶颈

c++ - 数据实际上是如何隐藏在一个类中的?

c++ - 树容器迭代器接口(interface)

c++ - 使用 std::binomial_distribution 在范围之间生成随机数

c++ - 复杂的 C 风格类型转换表达式如何工作?

c++ - 是否存在检测有符号类型的位移位操作的 GCC 警告?

C++ : Storing weight for larger Graph