C++ 理解qthreads-在线程之间共享数据
我开始了解使用线程的机制,但我想我被卡住了 如果我理解,我必须创建自己的类,释放run方法,然后创建线程 问题是,我的线程必须从guimain线程读取一些变量,如果使用它们,它将创建一些其他变量,main窗口将读取并打印这些变量 问题是,我正在接收一个蓝牙连接,它必须在线程中始终处于活动状态,但gui必须绘制从该线程读取的值 这是需要在分离线程上执行的函数:C++ 理解qthreads-在线程之间共享数据,c++,multithreading,qt,qthread,C++,Multithreading,Qt,Qthread,我开始了解使用线程的机制,但我想我被卡住了 如果我理解,我必须创建自己的类,释放run方法,然后创建线程 问题是,我的线程必须从guimain线程读取一些变量,如果使用它们,它将创建一些其他变量,main窗口将读取并打印这些变量 问题是,我正在接收一个蓝牙连接,它必须在线程中始终处于活动状态,但gui必须绘制从该线程读取的值 这是需要在分离线程上执行的函数: // Listen to the device for data void gui::listen_device() { unsi
// Listen to the device for data
void gui::listen_device()
{
unsigned char buf[10];
unsigned char crcval;
fd_set readmask;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 28000;
memset (buf, 0, 10);
int v = 0, v1 = 0, v2 = 0;
while(1)
{
int i;
FD_ZERO (&readmask);
FD_SET (sock, &readmask);
if (select (255, &readmask, NULL, NULL, &tv) > 0)
{
if (FD_ISSET (sock, &readmask))
{
int numb;
numb = 0;
numb = recv (sock, buf, 10, MSG_WAITALL);
crcval = BP_CRC8 (buf, 9);
// 8 bits
if (ui->comboBox->currentIndex() == 0)
{
if (crcval == buf[9])
{
s++;
// Print of counter
printf ("%d ->", buf[0]);
fprintf (data, "%d,", buf[0]);
for (int i = 1; i < 9; i++)
{
v = buf[i];
printf ("%d,", v);
fprintf (data, "%d,", v);
}
printf ("\n");
fprintf (data, "\n");
//fprintf(data, "s: %d, f: %d\n", s,f);
}
else
{
f++;
}
}
// 12 bits
else if (ui->comboBox->currentIndex() == 1)
{
if (numb == 14)
{
// Print of counter
printf ("%d,", buf[0]);
fprintf (data, "%d,", buf[0]);
for (i = 1; i < numb - 1; i += 3)
{
v1 = buf[i] | ((buf[i + 1] & 0x0F) << 8);
v2 = buf[i + 2];
v2 = (v2 << 4) | ((buf[i + 1] & 0xf0) >> 4);
printf ("%d,%d,", v1, v2);
fprintf (data, "%d,%d,", v1, v2);
}
printf ("\n");
fprintf (data, "\n");
}
}
}
}
}
}
这是一篇关于在Qt中使用线程的好文章
这是一篇关于在Qt中使用线程的好文章
有几种方法可以解决这个问题。如前所述,您可以使用互斥体。使用QByteArray的排队连接(例如void somethingQByteArray参数或QThreadStorage)都是可行的解决方案,尽管前者更简单,可能最适合您的情况
另外,永远不要将QThread子类化。改用QObject和moveToThread。QThread驻留在主线程中,只管理它创建的线程。如果在使用moveToThread之前将信号连接到对象,请确保在QObject::connect中使用Qt::QueuedConnection参数。有几种方法可以实现这一点。如前所述,您可以使用互斥体。使用QByteArray的排队连接(例如void somethingQByteArray参数或QThreadStorage)都是可行的解决方案,尽管前者更简单,可能最适合您的情况
另外,永远不要将QThread子类化。改用QObject和moveToThread。QThread驻留在主线程中,只管理它创建的线程。如果在使用moveToThread之前将信号连接到对象,请确保使用QObject::connect中的Qt::QueuedConnection参数。阅读特定互斥体和锁中的线程同步。调用select然后使用recvMSG_WAITALL是毫无意义的。您之所以调用select,是因为您不想无限期地阻止读取。但是,然后你专门设计你的read调用,要求它无限期地阻塞!可以将buf设置为全局变量或成员变量。与不同的进程不同,单个进程中的所有线程都已共享内存。但是,某些GUI功能在其他线程中无法工作,但仅访问变量应该可以正常工作。@DavidSchwartz您是对的。我忘了把它擦掉。在我阅读而不是recv之前,所以我没有标志。@SamuelNLP:你试过使用信号和插槽吗?您可以很容易地发出新数据已准备就绪的信号,并为GUI提供一些处理数据的时间。阅读有关线程同步的信息,特别是互斥锁和锁。调用select然后使用recvMSG_WAITALL进行后续操作毫无意义。您之所以调用select,是因为您不想无限期地阻止读取。但是,然后你专门设计你的read调用,要求它无限期地阻塞!可以将buf设置为全局变量或成员变量。与不同的进程不同,单个进程中的所有线程都已共享内存。但是,某些GUI功能在其他线程中无法工作,但仅访问变量应该可以正常工作。@DavidSchwartz您是对的。我忘了把它擦掉。在我阅读而不是recv之前,所以我没有标志。@SamuelNLP:你试过使用信号和插槽吗?您可以很容易地发出新数据准备就绪的信号,并给GUI一些槽来处理数据。千万不要说“永不”。在一些非常有效的情况下,可以将QThread子类化。事实上,官方的Never-say-Never中甚至直接提供了一个子类化示例。在一些非常有效的情况下,可以将QThread子类化。事实上,官方文档中甚至直接提供了子类化示例
void QMyThread::run()
{
listen_device();
}