Qt,多线程上下文切换与QRadioButtons

Qt, multithreading context switching with QRadioButtons

本文关键字:QRadioButtons 上下文切换 多线程 Qt      更新时间:2023-10-16

嗨,伙计们,所以我试着用我现在的方式在不同的线程之间切换,让用户在多个单选按钮之间来回切换(这里我只显示了2),当他们切换程序冻结。我想创建一个线程,停止它然后在进行单选按钮切换时创建另一个线程。我该如何做到这一点?

mainwindow.cpp

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    s1_thread = new skype_thread(this);
    connect(s1_thread, SIGNAL(skype_sig(int)), this, SLOT(skype_change(int)));
    x1_thread = new xlite_thread(this);
    connect(x1_thread, SIGNAL(xlite_sig(int)), this, SLOT(xlite_change(int)));
}
void MainWindow::on_radioButton_3_toggled(bool checked) //Skype Application is checked
{
    x1_thread->stop=true;
    s1_thread->start();
}
void MainWindow::on_radioButton_toggled(bool checked) //X-Lite Application is checked
{
    s1_thread->stop=true;
    x1_thread->start();
}

skype_thread.cpp:

void skype_thread::run()
{
    int err;
    int skype_signal=0;
    //Add programs you would like to use telephony hid here.
    wchar_t skype[6] = L"Skype";
    unsigned char data_usb[2];
    int transfer_size = 4;
    //Keyboard input event
    INPUT ip;
    //Device Handle
    libusb_device_handle* dev;
    //Initialize libusb with default device
    libusb_init(NULL);
    //Check whether the Red Button is meant to be a Hangup or Reject Button.
    bool check_d = 0;
    //Open Device VID = 0x04B4, PID = 0xE002 with the default libusb context
    dev = libusb_open_device_with_vid_pid(NULL, VID, PID);
    //Claim interface 3 on the device
    err = libusb_claim_interface(dev, 3);
    //Get first window on desktop
    HWND firstwindow = FindWindowEx(NULL, NULL, NULL, NULL);
    HWND window = firstwindow;
    wchar_t windowtext[MAX_PATH]; //search term
    //We need to get the console title in case we
    //accidentally match the search word with it
    //instead of the intended target window.
    wchar_t consoletitle[MAX_PATH];
    GetConsoleTitle(consoletitle, MAX_PATH);
    //Error message for when window isn't found.
    QString error_msg = NULL;
    while(true){
        //Check window title for a match
        GetWindowText(window, windowtext, MAX_PATH);
        if (wcsstr(windowtext, skype)!=NULL && wcscmp(windowtext, consoletitle)!=0) break; //search for program
           window = FindWindowEx(NULL, window, NULL, NULL); //Get next window
    }
    while(true){
        QMutex mutex;
        mutex.lock();
        //Differentiate the different button presses.
        //Interrupt IN transfer
        err = libusb_interrupt_transfer(dev, LIBUSB_ENDPOINT_IN | EP_IN, data_usb, sizeof(data_usb), &transfer_size, 1000);
          if(transfer_size > 0){
              if(data_usb[0]==0x02 && data_usb[1]==0x04){ //Pickup Button Payload
              printf("Window found: %lsn", windowtext);
              //Press the "Alt" key
              ip.ki.wVk = 0x12; // virtual-key code for the "Alt" key
              ip.ki.dwFlags = 0; // 0 for key press
              SendInput(1, &ip, sizeof(INPUT));
              //Release the "Alt" key
              ip.ki.wVk = 0x12;
              ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
              SendInput(1, &ip, sizeof(INPUT));
              //Bring specified window into focus
              SetForegroundWindow(window);
              //Press the "Alt" key
              ip.ki.wVk = 0x12; // virtual-key code for the "alt" key
              ip.ki.dwFlags = 0; // 0 for key press
              SendInput(1, &ip, sizeof(INPUT));
              //Press the "Pageup" key
              ip.ki.wVk = 0x21; // virtual-key code for the "pageup" key
              ip.ki.dwFlags = 0; // 0 for key press
              SendInput(1, &ip, sizeof(INPUT));
              //Release the "Pageup" key
              ip.ki.wVk = 0x21;
              ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
              SendInput(1, &ip, sizeof(INPUT));
              //Release the "Alt" key
              ip.ki.wVk = 0x12;
              ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
              SendInput(1, &ip, sizeof(INPUT));
              check_d = 1;
           }
           if(data_usb[0]==0x02 && data_usb[1]==0x01 && check_d==1){ //Disconnect Button Payload
               //Press the "Alt" key
               ip.ki.wVk = 0x12; // virtual-key code for the "Alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Alt" key
               ip.ki.wVk = 0x12;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Bring specified window into focus
               SetForegroundWindow(window);
               //Press the "Alt" key
               ip.ki.wVk = 0x12; // virtual-key code for the "alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Press the "Pagedown" key
               ip.ki.wVk = 0x22; // virtual-key code for the "pageup" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Pagedown" key
               ip.ki.wVk = 0x22;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Alt" key
               ip.ki.wVk = 0x12;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               check_d = 0;
           }//end if
           if(data_usb[0]==0x02 && data_usb[1]==0x01 && check_d==0){ //Reject Button Payload
               //Press the "Alt" key
               ip.ki.wVk = 0x12; // virtual-key code for the "Alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Alt" key
               ip.ki.wVk = 0x12;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Bring specified window into focus
               SetForegroundWindow(window);
               //Press the "Ctrl"Key
               ip.ki.wVk = 0x11; // virtual-key code for the "alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Press the "Alt" key
               ip.ki.wVk = 0x12; // virtual-key code for the "alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Press the "Pagedown" key
               ip.ki.wVk = 0x22; // virtual-key code for the "pageup" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Pagedown" key
               ip.ki.wVk = 0x22;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Alt" key
               ip.ki.wVk = 0x12;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Ctrl" key
               ip.ki.wVk = 0x11;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               check_d = 0;
           }//end if
       }//end if
       if(this->stop) break;
       mutex.unlock();
       emit skype_sig(skype_signal);
       skype_signal++;
   } //end while
}

xlite_thread.cpp

void xlite_thread::run()
{
    int xlite_signal=0;
    int err;
    //Add programs you would like to use telephony hid here.
    wchar_t xlite[7] = L"X-Lite";
    unsigned char data_usb[2];
    int transfer_size = 4;
    //Keyboard input event
    INPUT ip;
    //Device Handle
    libusb_device_handle* dev;
    //Initialize libusb with default device
    libusb_init(NULL);
    //Check whether the Red Button is meant to be a Hangup or Reject Button.
    bool check_d = 0;
    //Open Device VID = 0x04B4, PID = 0xE002 with the default libusb context
    dev = libusb_open_device_with_vid_pid(NULL, VID, PID);
    //Claim interface 3 on the device
    err = libusb_claim_interface(dev, 3);
    //Get first window on desktop
    HWND firstwindow = FindWindowEx(NULL, NULL, NULL, NULL);
    HWND window = firstwindow;
    wchar_t windowtext[MAX_PATH]; //search term
    //We need to get the console title in case we
    //accidentally match the search word with it
    //instead of the intended target window.
    wchar_t consoletitle[MAX_PATH];
    GetConsoleTitle(consoletitle, MAX_PATH);
   //Error message for when window isn't found.
    QString error_msg = NULL;
    while(true){
        //Check window title for a match
        GetWindowText(window, windowtext, MAX_PATH);
        if (wcsstr(windowtext, xlite)!=NULL && wcscmp(windowtext, consoletitle)!=0) break; //search for program
            window = FindWindowEx(NULL, window, NULL, NULL); //Get next window
    }
    while(true){
        QMutex mutex;
        mutex.lock();
        //Differentiate the different button presses.
        //Interrupt IN transfer
        err = libusb_interrupt_transfer(dev, LIBUSB_ENDPOINT_IN | EP_IN, data_usb, sizeof(data_usb), &transfer_size, 1000);
        if(transfer_size > 0){
           if(data_usb[0]==0x02 && data_usb[1]==0x04){ //Pickup Button Payload
               printf("Window found: %lsn", windowtext);
               //Press the "Alt" key
               ip.ki.wVk = 0x12; // virtual-key code for the "Alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Alt" key
               ip.ki.wVk = 0x12;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Bring specified window into focus
               SetForegroundWindow(window);
               //Press the "Ctrl" key
               ip.ki.wVk = 0xA2; // virtual-key code for the "alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Press the "N" key
               ip.ki.wVk = 0x4E; // virtual-key code for the "pageup" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "N" key
               ip.ki.wVk = 0x4E;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Ctrl" key
               ip.ki.wVk = 0xA2;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               check_d = 1;
           }
           if(data_usb[0]==0x02 && data_usb[1]==0x01 && check_d==1){ //Disconnect Button Payload
               //Press the "Alt" key
               ip.ki.wVk = 0x12; // virtual-key code for the "Alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Alt" key
               ip.ki.wVk = 0x12;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Bring specified window into focus
               SetForegroundWindow(window);
               //Press the "Ctrl" key
               ip.ki.wVk = 0xA2; // virtual-key code for the "alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Press the "E" key
               ip.ki.wVk = 0x45; // virtual-key code for the "pageup" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "E" key
               ip.ki.wVk = 0x45;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Ctrl" key
               ip.ki.wVk = 0xA2;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               check_d = 0;
           }//end if
           if(data_usb[0]==0x02 && data_usb[1]==0x01 && check_d==0){ //Reject Button Payload
               //Press the "Alt" key
               ip.ki.wVk = 0x12; // virtual-key code for the "Alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Alt" key
               ip.ki.wVk = 0x12;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Bring specified window into focus
               SetForegroundWindow(window);
               //Press the "Ctrl" key
               ip.ki.wVk = 0xA2; // virtual-key code for the "alt" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Press the "D" key
               ip.ki.wVk = 0x44; // virtual-key code for the "pageup" key
               ip.ki.dwFlags = 0; // 0 for key press
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "D" key
               ip.ki.wVk = 0x44;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               //Release the "Ctrl" key
               ip.ki.wVk = 0xA2;
               ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
               SendInput(1, &ip, sizeof(INPUT));
               check_d = 0;
           }//end if
       }//end if
       if(this->stop) break;
       mutex.unlock();
       emit xlite_sig(xlite_signal);
       xlite_signal++;
   } //end while
}

您最好使用对象和计时器来重复调用对象中的插槽(该插槽被移动到工作线程)

例如:

class SkypeObject: public QObject{
    Q_OBJECT
slots:
    void start();
    void loop();
    void stop();
signals:
    //...
}

然后在将其移动到后台线程后触发startstop插槽。在循环槽内,您将while的主体并通过QTimer触发它(或使用startTimer并继承timerEvent(QTimerEvent))

而且,while循环中的互斥锁实际上并没有做任何事情来防止竞争条件,除了当stop为真时退出while时发生泄漏。