C++ 从事件处理程序中获取数据并传递给另一个类的方法?

Posted

技术标签:

【中文标题】C++ 从事件处理程序中获取数据并传递给另一个类的方法?【英文标题】:C++ Getting Data out of Event Handler and Pass to Method of Another Class? 【发布时间】:2016-07-05 18:03:46 【问题描述】:

所以,我让自己陷入了困境。我正在制作一种类似于示波器的程序,它分为一个主类、一个串行端口处理类和一个处理 FFT 实际性能的类。 Serial Handler 类使用 boost.Asio 的异步读取功能从串行端口读取数据,然后我想将这些数据传递给 FFT 处理类的成员函数。该设置非常适合阅读。我有一个 io_service 对象在一个单独的线程上运行,当有数据要读取时,它会调用一个事件处理程序。

这就是问题所在。不知何故,我需要找到一种方法将数据从 async_read_some 的事件处理程序传递到一个单独的类的方法,该类也恰好位于另一个线程上。我什至不知道这是否可能完全诚实。虽然这两个类确实存在于 main 方法中,所以我认为可以在它们之间传递数据。即使这是不可能的,有什么方法可以达到预期的效果?我想最坏的情况可能会将它们合并到一个类中。

编辑:这里有一些快速的伪代码,只是为了更好地了解所有这些如何链接在一起。免责声明:我不完全确定如何正确编写伪代码,我是一个有点自私的程序员,所以如果它不是太容易理解,请告诉我,我会看看我能做些什么来解决它:

//declared globally
boost::mutex mutex_;
sem_t qSem;
queue q;


class SerialHandler
private:
    string portName;
public:
    void StartConnection()

        //...some initialization things

        AsyncReadSome();

        //thread is initiated here
        t1 = new boost::thread(boost::bind(&boost::asio::io_service::run, &ioservice));
    

    //the only important thing here is it reads into a buffer and calls the event after the read
    void AsyncReadSome()
        serialPort->async_read_some(boost::asio::buffer(rawBuffer, SERIAL_PORT_READ_BUFF_SIZE),
        boost::bind(&SerialHandler::HandlePortOnReceive,
        this, placeholders::error,
        placeholders::bytes_transferred, q));
    

    void HandlePortOnReceive( error_code &ec, size_t bytes_transferred, queue q)
        scoped_lock (mutex_); //from boost lib

        for (int i=0;i<bytes_transferred;i++)
            double d = (double) rawBuffer[i];  //pushes data into queue
            q.push(c);
            sem_post(&qSem);
        
        AsyncReadSome(); //loops back on itself
    



class FFTHandler
private:
    double *in; //holds the input array
    fftw_complex *out;//holds out array

    int currentIndex;
public:
     void AppendIn(queue &q, sem_t &_qSem)
         while (1)
             sem_wait(&_qSem);
             double d = q.pop();
             in[currentIndex] = d;
             if (...)//some logic to not overflow the in[]
         
     



int main()
     FFTHandler fftHandler;
     SerialHandler serialHandler;

     //...some initialization of global variables goes here

     serialHandler.StartConnection();

     boost::thread *t2=new boost::thread(boost::bind(&FFTHandler.AppendIn, &fftHandler, &q, &qSem);

     char c = getchar();
     if (c)call stop functionality


【问题讨论】:

你看boost signals了吗? @mvidelgauz 我从来没有使用过 boost::signals2 所以你必须原谅我的无知,但是,从我对文档和教程的阅读来看,我不完全确定如何我将能够使用它将数据从事件处理程序传递到我的主线程上的类。您介意详细说明吗? 抱歉,目前没有我的旧项目代码。如果到明天晚上没有人会回答,我会尝试找到代码示例。同时,您也可以搜索它(也许使用“site:***.com”:-))。我敢肯定有很多 【参考方案1】:

免责声明: 我从未使用过 boost::signals,所以这可能是更好的解决方案。我快速浏览了 mvidelgauz 发布的链接,它看起来很不错。

以下是我在线程之间共享数据的方式: 有一个全局变量,其中包含您需要在线程之间共享的数据。根据我对您的情况的了解,我会使用某种 FIFO。当串行处理程序类事件处理程序从串行端口读取数据并将其存储在共享 FIFO 中时(确保在访问共享变量时使用互斥锁),发布到信号量。单独线程中单独类中的方法应等待该信号量。当串行处理程序线程发布到信号量时,单独的线程将被唤醒,您将知道可以从 FIFO 中读取数据。同样,确保在从 FIFO 读取之前使用互斥锁。就个人而言,我对 pthread 很熟悉,所以我会使用它。

在不知道您的代码如何工作的情况下,我会尽力而为。这是一些伪代码:

#include <pthread.h>
#include <semaphore.h>

// Global variable
Queue q;
pthread_mutex_t q_mutex;
sem_t q_sem;
// Make sure to initialize these variables somewhere

// Serial thread event handler:
char c = serial_port_read(); // I don't know how this works for you
pthread_mutex_lock(&q_mutex);
q.push(c);
pthread_mutex_unlock(&q_mutex);
sem_post(&q_sem);
return;

// Separate thread that waits for this data
sem_wait(&q_sem);
pthread_mutex_lock(&q_mutex);
char c = q.pop();
pthread_mutex_unlock(&q_mutex);

如果您有任何问题,请告诉我。

【讨论】:

我继续尝试了您的方法(我现在将其包含在上面),但我不完全确定我这样做是否正确。信号量是否通知另一个线程有数据要弹出然后允许它弹出?我觉得我根本没有告诉我的程序何时调用 AppendIn()。我可以将它包含在 main() 中吗? 是的,信号量实际上只是一个信号。如果信号量的值为 0,则等待信号量会阻塞线程。发送到信号量只会增加信号量;发生这种情况时,另一个线程会唤醒,减少信号量,然后继续。对 AppendIn() 的调用应该在 while(1) 循环中,以便它始终被调用。这可能在 main 中,但由于看起来 main 还需要做其他事情,所以它应该是它自己的线程。另外,我看到您锁定了一次互斥锁,但您永远不会解锁它。你能解释一下你在用 scoped_lock (mutex_) 做什么吗? 我使用 scoped_lock 主要是为了方便,因为它仅在函数超出范围然后自动解锁之前充当锁。以防万一发生一些不可预见的错误并导致我的函数在没有解锁互斥锁的情况下返回。我会用我所做的更改来更新问题,看看它是否有效 哇,这真是太棒了。谢谢你的解释。祝您好运,如果您有任何其他问题,请告诉我。

以上是关于C++ 从事件处理程序中获取数据并传递给另一个类的方法?的主要内容,如果未能解决你的问题,请参考以下文章

从 JSON 中获取值并传递给另一个视图

将二维数组传递给另一个类 C++

从一个文本字段中获取文本,对其进行更改并传递给另一个文本字段

C ++将类的引用传递给另一个类

双击datagridview中的行并获取特定单元格的值并将其传递给另一个表单

使用 Cython 时如何将一个 C++ 类(引用)传递给另一个?