嵌套函数调用c ++线程

时间:2016-03-29 14:44:39

标签: c++ multithreading nested

我遇到了线程问题,我一直试图在SO和Google上找到答案,但没有运气。

简单地说,我想创建一个可以执行一个函数的线程,该函数使用另一个函数作为参数(带有自己的参数 - 见下文)。

我已经按照这些指南(https://www.justsoftwaresolutions.co.uk/threading/multithreading-in-c++0x-part-2-function-objects-and-arguments.html)对线程进行了完美无缺的处理,除了上面提到的用例。

这是我尝试创建线程的特定行:

std::thread t(executeQuery, buildQuery(*_mVecHistIter, symbol));

这些是嵌套函数定义:

std::wstring database_con::buildQuery(vector<std::wstring> input, string symbol)
void database_con::executeQuery(wstring query)

错误:

  

没有构造函数的实例&#34; std :: thread :: thread&#34;匹配参数   列表

我可以简单地重建这些函数,以便buildQuery启动executeQuery。但是我想分开这些电话并确保尽可能多地从班级&#34; body&#34;为了便于阅读和维护。

任何有关该主题的更多资料的建议,指示或想法都将不胜感激! :)

我正在使用 MSVC 2015。

修改

#include "stdafx.h"
#include "database_con.h"

////////////////////////////////////////////////////////////////////////
// Show errors from the SQLHANDLE

void database_con::show_error(unsigned int handletype, const SQLHANDLE& handle)
{
    SQLWCHAR sqlstate[1024];
    SQLWCHAR message[1024];
    if (SQL_SUCCESS == SQLGetDiagRec(handletype, handle, 1, sqlstate, NULL, message, 1024, NULL))
        wcout << "Message: " << message << "\nSQLSTATE: " << sqlstate << endl;
}

std::wstring database_con::StringToWString(const std::string& s)
{
    std::wstring temp(s.length(), L' ');
    std::copy(s.begin(), s.end(), temp.begin());
    return temp;
}

////////////////////////////////////////////////////////////////////////
// Builds the stored procedure query.

std::wstring database_con::buildQuery(vector<std::wstring> input, string symbol)
{
    std::wstringstream builder;
    builder << L"EXEC sp_addHistorical " << "@Symbol='" << L"" << StringToWString(symbol) << "'," <<
        "@Date='" << (wstring)L"" << input.at(0) << "'," <<
        "@Open=" << (wstring)L"" << input.at(1) << "," <<
        "@Close=" << (wstring)L"" << input.at(2) << "," <<
        "@MaxPrice=" << (wstring)L"" << input.at(3) << "," <<
        "@MinPrice=" << (wstring)L"" << input.at(4) << "," <<
        "@Volume=" << (wstring)L"" << input.at(5) << ";";
    return builder.str();
}

void database_con::executeQuery(wstring query) {

    if (SQL_SUCCESS != SQLExecDirectW(stmt, const_cast<SQLWCHAR*>(query.c_str()), SQL_NTS)) {
        std::cout << "Execute error " << std::endl;
        show_error(SQL_HANDLE_STMT, stmt);
        std::wcout << L"Unsuccessful Query: " << query << std::endl;
    }
    // Close Cursor before next iteration starts:
    SQLRETURN closeCursRet = SQLFreeStmt(stmt, SQL_CLOSE);
    if (!SQL_SUCCEEDED(closeCursRet))
    {
        show_error(SQL_HANDLE_STMT, stmt);
        // maybe add some handling for the case that closing failed.
    }
}
////////////////////////////////////////////////////////////////////////
// Constructs a database connector object with the historical data and its symbol

database_con::database_con(std::vector<std::vector<std::wstring>> historical, string symbol){
    /*
    Set up the handlers
    */

    /* Allocate an environment handle */
    SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
    /* We want ODBC 3 support */
    SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
    /* Allocate a connection handle */
    SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);

    /* Connect to the DSN */
    SQLDriverConnectW(dbc, NULL, L"DRIVER={SQL Server};SERVER=ERA-PC-STUART\\JBK_DB;DATABASE=master;UID=geo;PWD=kalle123;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
    /* Check for success */
    if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt))
    {
        show_error(SQL_HANDLE_DBC, dbc);
        std::cout << "Failed to connect";
    }
    std::cout << "Building and executing the query" << std::endl;

    for (_mVecHistIter = historical.begin();
        _mVecHistIter != historical.end();
        _mVecHistIter+5) {
        std::thread t(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
        std::thread t2(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
        std::thread t3(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
        std::thread t4(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
        std::thread t5(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol));
        t.join();
        t2.join();
        t3.join();
        t4.join();
        t5.join();

        //executeQuery(buildQuery(*_mVecHistIter, symbol)); 

    }

    /*_mSymbol = symbol;
    std::wstringstream stream(StringToWString(historical));
    std::wstring line;
    int row = 0;
    while (std::getline(stream, line)) {
        if (row > 0) {
            vector<wstring> vHistorical = parseData(L"" + line, ',');
            std::wstring SQL = buildQuery(vHistorical, _mSymbol);
            if (SQL_SUCCESS != SQLExecDirectW(stmt, const_cast<SQLWCHAR*>(SQL.c_str()), SQL_NTS)) {
                std::cout << "Execute error " << std::endl;
                show_error(SQL_HANDLE_STMT, stmt);
                std::wcout << L"Unsuccessful Query: " << SQL << std::endl;
            }
            // Close Cursor before next iteration starts:
            SQLRETURN closeCursRet = SQLFreeStmt(stmt, SQL_CLOSE);
            if (!SQL_SUCCEEDED(closeCursRet))
            {
                show_error(SQL_HANDLE_STMT, stmt);
                // maybe add some handling for the case that closing failed.
            }
        }
        row++;
    }*/
    std::cout << "Query " << _mSymbol << " ready" << std::endl;

}

database_con::~database_con() {
    std::cout << "The database object has been deleted" << std::endl;
}

1 个答案:

答案 0 :(得分:2)

好吧,我可能误解了这个问题。您不希望使用函数创建一个线程,让其中一个参数成为另一个函数。而是使用函数创建一个线程,并让其参数由另一个函数计算。没有什么特别的。您可能只是忘记添加&运算符来获取函数的地址。

std::thread t(&executeQuery, buildQuery(*_mVecHistIter, symbol));
              ^-- note the &

修改
所以,你忘记提到database_con是一个类。为了使用类成员函数作为函数接受指针的参数作为参数(在您的情况下为std::thread::thread),您必须使用带有操作数&&database_con::executeQuery)的完全限定名称。但是,由于这是非静态成员函数,它将需要其第一个参数指针指向此类对象的实例(google std :: thread非静态成员函数)。

std::thread t(&database_con::executeQuery, this, buildQuery(*_mVecHistIter, symbol));

以前的回答

您是否考虑过使用std::function

#include <functional>
#include <thread>

int foo(int arg1, int arg2)
{
    return arg1 + arg2;
}
void bar(std::function<int(int, int)> fnc, int arg1, int arg2)
{
    fnc(arg1, arg2);
}
int main()
{
    std::thread thr{&bar, &foo, 1, 2};
}