0

我正在为 RS232 端口编写小班课程。它可以同步写入和异步读取。因此,对于异步读取,我正在使用第二个线程,即等待输入数据。收到数据后,我想用输入数据调用用户回调(我作为构造函数参数获得)。它看起来像:

typedef int (*ReceivedCallback)(string data);

class RS232
{
    RS232(string portName, ReceivedCallback dataReceived);
    ~RS232();

private:
    ReceivedCallback dataReceivedCallback;

private:
    static unsigned ReaderThread(void* data);

public:
    SendData(string data);
}

我的问题是:ReaderThread 必须是静态的才能将指向它的指针传递给 _beginthreadex() 函数。在 ReaderThread 我想调用“dataReceivedCallback”,从构造函数中的用户获得。但我不能,因为我不能在静态 ReaderThread 中调用非静态函数。另外,我不能将“dataReceivedCallback”设为静态,因为我的类可能有很多实例(对于 COM1、COM2、COM3),并且每个实例都应该有自己的回调,由用户获取。

我的架构错误在哪里?你将如何实施它?

提前致谢!

PS 使用 Visual Studio 2005。

4

3 回答 3

2

You need to pass a pointer to the instance of RS232 to ReaderThread, which will, in turn, either pass that pointer to a static callback, or directly call non-static methods on the RS232 object.

I would also use [CreateThread][1] rather than beginthreadex. My code samples will use CreateThread, but you can adapt the technique to beginthreadex if you so desire.

Simply, when kicking off the ReaderThread, pass it a pointer to the instance:

RS232* myObj = new RS232;
CreateThread (..., myObj);

...use reinterpret_cast to cast it back:

unsigned RS232::ReaderThread (void* data)
{
  RS232* that = reinterpret_cast <RS232*> (data);
}

Change your callback function so that it can pass the instance as well:

typedef int (*ReceivedCallback)(string data, RS232* that);

And now in the callback you can call member functions:

that->DoSomethingCool (data);
于 2013-07-11T13:26:05.053 回答
1

您需要将一个额外的参数传递给线程函数(您已经有一个void *data可用的参数)。

现在,将其添加为您的私有元素class RS232

class RS232
{

     RS232(string portName, ReceivedCallback dataReceived);
    ~RS232();

private:
    ReceivedCallback dataReceivedCallback;

private:
    static unsigned ReaderThread(void* data);

public:
    SendData(string data);
}

在构造函数中:

RS232::RS232(string portName, ReceivedCallback dataReceived)
{
   ... various stuff to initialize the serial port ... 
   _beginthreadex(securityarg, stacksize, ReaderThread, this, ...)
}

在 ReaderThread 函数中:

unsigned RS232::ReaderThread(void *data)
{
   RS232 *self = static_cast<RS232*>(data);

   .... stuff to read from serial port ... 

   ... Now call the callback:
   self->dataReceivedCallback(str); 
   .... 
}
于 2013-07-11T13:23:43.567 回答
1

要访问静态线程函数中的非静态对象数据,您可以使用这个极其 hacky 且未经测试的解决方案。但请注意 --- 它仅用于教育目的,因为它非常hacky。您应该了解锁和互斥锁,并可能提升线程。请注意,这是一个 pthread 样式的解决方案。我对函数 _beginthreadex() 没有经验,但您可以看到 createThread 完成了创建线程的工作。根据需要进行调整。

typedef int (*ReceivedCallback)(string data);

class RS232
{
public:
    RS232(string portName, ReceivedCallback dataReceived);
    ~RS232();
    SendData(string data);
    createThread();

private:
    ReceivedCallback dataReceivedCallback;
    static unsigned ReaderThread(void* data);
    thread m_someThread;

    struct accessHelper
    {
        RS232* This;
        void *actual_arg;
        accessHelper(RS232 *t, void *p)  
            : This(t), 
              actual_arg(p) 
              {}
    };

};

RS232::createThreaad()
{
     int someData;
     accessHelper ah(this, someData);
     m_someThread.create(RS232::ReaderThread, &ah);
}

RS232::ReaderThread(void *data) 
{
    accessHelper *ah = static_cast<accessHelper*>(data);
    RS232 *This = ah->This;
    This->dataReceivedCallback......
}
于 2013-07-11T13:31:11.220 回答