понимание qthreads - обмен данными между потоками

Я начинаю понимать механизм использования потоков, но, похоже, я застрял,

Если я понял, мне нужно создать свой собственный класс, выпустить метод run(), а затем создать поток.

проблема в том, что мой поток должен прочитать из графического интерфейса (основной поток) некоторые переменные, и, используя их, он создаст некоторые другие переменные, которые основное окно будет читать и отображать.

дело в том, что я получаю соединение Bluetooth, которое должно быть всегда активным в потоке, но графический интерфейс должен отображать значения, считанные из этого потока.

это функция, которая должна быть в отдельном потоке:

// 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");
                    }
                }
            }
        }
    }
}

и некоторые из этих читаемых здесь переменных являются глобальными, как sock, data, and the ui->combobox.

Я хочу, чтобы buf был доступен для главного окна.

Любой совет?

ОБНОВИТЬ:

почему это неправильно?

void QMyThread::run()
{
    listen_device();
}

person SamuelNLP    schedule 06.03.2013    source источник
comment
читайте о синхронизации потоков, в частности о мьютексах и блокировках.   -  person Ivaylo Strandjev    schedule 06.03.2013
comment
Нет никакого смысла вызывать select, а затем recv(MSG_WAITALL). Вы звоните select, потому что не хотите блокировать чтение на неопределенный срок. Но затем вы специально создаете свой вызов чтения, прося его заблокировать на неопределенный срок!   -  person David Schwartz    schedule 06.03.2013
comment
Вы можете сделать buf глобальной переменной или переменной-членом. В отличие от разных процессов, все потоки в одном процессе уже совместно используют память. Однако некоторые функции графического интерфейса не будут работать из других потоков, но просто доступ к переменным должен работать нормально.   -  person Some programmer dude    schedule 06.03.2013
comment
@DavidSchwartz, ты прав. Я забыл его стереть. Раньше у меня было read вместо recv, и поэтому у меня не было флага.   -  person SamuelNLP    schedule 06.03.2013
comment
@SamuelNLP: Вы пробовали использовать сигналы и слоты? Вы можете легко сигнализировать о том, что новые данные готовы, и дать своему графическому интерфейсу некоторый слот для обработки данных.   -  person Zeta    schedule 06.03.2013
comment
поскольку у меня есть while(1), он заблокирует мой графический интерфейс, если он не находится в другом потоке.   -  person SamuelNLP    schedule 06.03.2013
comment
Если у вас нет явных причин для использования потоков, не делайте этого. Просто используйте QIODevice стандартным способом Qt в основном потоке. Если задержка (либо в графическом интерфейсе, либо в сети, либо в обоих случаях) становится заметной, переместите связь в новый поток.   -  person hyde    schedule 06.03.2013


Ответы (2)


Вот хорошая статья об использовании потоков в Qt
http://qt-project.org/doc/qt-5.0/qtcore/thread-basics.html

person spiritwolfform    schedule 06.03.2013

Есть несколько способов сделать это. Как уже упоминалось, вы можете использовать мьютексы. Соединение в очереди с параметром QByteArray (например, void something(QByteArray) ) или QThreadStorage — оба рабочих решения, хотя первое проще и, вероятно, наиболее подходит для вашей ситуации.

Кроме того, никогда не подкласс QThread. Вместо этого используйте QObject и moveToThread(). QThread находится в основном потоке и просто управляет созданным им потоком. Если вы подключаете сигналы к объекту до использования moveToThread(), обязательно используйте аргумент Qt::QueuedConnection в QObject::connect().

person anonymous    schedule 02.04.2015
comment
Никогда не говори никогда. Существуют вполне допустимые ситуации, в которых можно создать подкласс QThread. На самом деле, пример подкласса даже предоставлен непосредственно в официальной документации QThread - person BrandonL; 07.06.2021