【问题标题】:How to pass function that is a member of a class to a thread? [duplicate]如何将作为类成员的函数传递给线程? [复制]
【发布时间】:2023-01-26 19:11:21
【问题描述】:

我正在编写一个 TCP 客户端,对于每个客户端的发送函数,我想为该特定客户端的消息或发出的请求启动一个线程。这意味着我的程序将有多个客户端,每个客户端都有自己的发送消息线程,因此我创建了一个 tcpClient 对象,每个客户端对象在发送消息时都应该有自己的线程。我的问题是我希望发送消息的函数也成为 tcpClient 对象的成员,并将此函数传递给 std::thread function 似乎是不可能的。我所有的相关代码如下所示。

我的头文件:

//tcpClient.hpp

#include <iostream>
#include <functional>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <string>
#include <thread>

class tcpClient
{
    private:

        int sock;
        int port = 5400;
        int ipAddressInt[4] = {127, 0, 0, 1};;
        sockaddr_in hint;
        int connectRes;
        char buf[4096];
        int sendRes;
        int bytesReceived;
        bool sendLock;
        std::thread thread;

        
    public:

        bool Init ();
        bool SendThread ();
        void Send ();
};

我的源代码:

// tcpClient.cpp

#include "./hdr/tcpip_client.hpp"

using namespace std;
using namespace std::placeholders;

bool tcpClient::Init ()
{
    //  Create a socket
    sock = socket(AF_INET, SOCK_STREAM, 0);

    if (sock == -1)
    {
        return 0;
    }

    // Create a hint structure for the server we're connecting with
    string ipAddress = "";

    for (int i = 0; i <=3; i++)
    {
        if (i < 3) 
        {
            ipAddress = ipAddress + to_string(ipAddressInt[i]) + ".";
        }
        else
        {
            ipAddress = ipAddress + to_string(ipAddressInt[i]);
        }
    }

    hint.sin_family = AF_INET;
    hint.sin_port = htons(port);
    inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);

    //  Connect to the server on the socket
    connectRes = connect(sock, (sockaddr*)&hint, sizeof(hint));

    if (connectRes == -1)
    {
        return 0;
    }

    return 1;
}

bool tcpClient::SendThread ()
{
    // Enter lines of text
    cout << "> ";
    string userInput;
    getline(cin, userInput);

    // Send to server
    sendRes = send(sock, userInput.c_str(), userInput.size() + 1, 0);
    if (sendRes == -1)
    {
        cout << "Could not send to server! Whoops!\r\n";
        return 0;
    }

    // Wait for response
    memset(buf, 0, 4096);
    bytesReceived = recv(sock, buf, 4096, 0);

    if (bytesReceived == -1)
    {
        cout << "There was an error getting response from server\r\n";
    }

    else
    {
        // Display response
        cout << "SERVER> " << string(buf, bytesReceived) << "\r\n";
    }
    return 1;
}

void tcpClient::Send ()
{
    
    this->thread = std::thread(/*temp*/);
    this->thread.join();
}

所以查看源文件,在void tcpClient::Send () /*temp*/ 是应该是bool SendThread () 的占位符。请注意,我的代码的网络部分不是问题,只是我似乎无法解析属于该类成员的函数这一事实才是我正在努力解决的问题。

谢谢你的帮助。

【问题讨论】:

  • 使用 lambda 函数。 m_future = std::async(std::launch::async, [&amp;]{ tcpClient.SendThread(); });。我发现 futures 与 RAII 和线程末尾的自动同步配合得很好。使 m_future 成为您的类的成员,您的类析构函数将与异步调用的结束同步。

标签: c++ multithreading


【解决方案1】:

首先,您需要传递对象作为参数调用 (this) 上的函数。

其次,您需要为要调用的函数传递一个显式指针(带有指向运算符&amp; 的指针)。

正如互联网上无数的例子所示:

thread = std::thread(&tcpClient::SendThread, this);

话虽如此,有几个问题:

首先,直接调用join并不会并行运行线程,就像调用函数一样。

其次,线程函数不应该有返回值。

【讨论】:

    【解决方案2】:

    【讨论】:

    • 请不要回答重复的问题。一旦您在此站点上获得足够的声誉,您就可以提交 cmet。
    猜你喜欢
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    相关资源
    最近更新 更多