类实例的std :: thread

时间:2012-12-25 03:25:00

标签: c++ multithreading class c++11

我正在尝试创建此类的两个实例,最终将使用Win32的mciSendString功能播放音乐文件。但是为了测试它,因为这是我第一次尝试使用std :: thread,我写了一个测试(void)方法,它输出类ID,我希望打印出一系列的1和2,如12122111112212121212 ...

我收到以下错误,test(void)方法确实存在?

错误1错误C2064:term不计算为采用0参数的函数

#include <iostream>
#include <thread>

typedef enum MusicStatus {
    MUSIC_PLAYING = 0, 
    MUSIC_PAUSED, 
    MUSIC_STOPPED, 
    MUSIC_IDLE
} MusicStatus, *pMusicStatus;

class MusicPlayer
{
public:

    MusicPlayer(void) {
        m_bIsPlaying = false;
        m_bIsPaused = false;
    }

    bool isPaused(void) {
        return m_bIsPaused;
    }

    bool isPlaying(void) {
        return m_bIsPlaying;
    }

    MusicStatus getState(void) {
        if ( !m_bIsPlaying && !m_bIsPaused && !m_bIsStopped )
            return MUSIC_IDLE;
        if ( m_bIsPlaying )
            return MUSIC_PLAYING;
        if ( m_bIsPaused ) 
            return MUSIC_PAUSED;
        if ( m_bIsStopped )
            return MUSIC_STOPPED;
        return MUSIC_STOPPED;
    }

    void test(void) {
        for ( int m = 0; m < 100; m++ ) {
            std::cout << this->n;
        }
    }

    int n;

private:

    bool m_bIsPlaying, m_bIsPaused, m_bIsStopped;

};


int main(int argc, char* argv[])
{
    MusicPlayer A;
    MusicPlayer B;
    A.n = 1;
    B.n = 2;

    std::thread t1(A);
    std::thread t2(B);

    t1.join();
    t2.join();

    A.test();
    B.test();

    system("PAUSE");
    return 0;
}

更新:我做了一些调整,现在我遇到了参数列表的问题,错误:MusicPlayer :: play_sound函数调用缺少参数列表

#include <iostream>

#pragma comment(lib, "Strmiids.lib") 

#include <thread>
#include <dshow.h>
#include "Lib/NSL.h"

typedef enum MusicStatus {
    MUSIC_PLAYING = 0, 
    MUSIC_PAUSED, 
    MUSIC_STOPPED, 
    MUSIC_IDLE
} MusicStatus, *pMusicStatus;

class MusicPlayer
{
public:

    MusicPlayer() {
        m_bIsPlaying = false;
        m_bIsPaused = false;
        m_bIsStopped = false;
    }

    bool isPaused() {
        return m_bIsPaused;
    }

    bool isPlaying() {
        return m_bIsPlaying;
    }

    MusicStatus getState() {
        if ( !m_bIsPlaying && !m_bIsPaused && !m_bIsStopped )
            return MUSIC_IDLE;
        if ( m_bIsPlaying )
            return MUSIC_PLAYING;
        if ( m_bIsPaused ) 
            return MUSIC_PAUSED;
        if ( m_bIsStopped )
            return MUSIC_STOPPED;
        return MUSIC_STOPPED;
    }

    void playAudio(std::string strFilePath) {
        m_strFilePath = strFilePath;
        std::thread audioThread(play_sound);
        audioThread.join();
    }

private:

    bool m_bIsPlaying, m_bIsPaused, m_bIsStopped;
    std::string m_strFilePath;

    void play_sound() {
        IGraphBuilder *pGraph = NULL;
        IMediaControl *pControl = NULL;
        IMediaEvent   *pEvent = NULL;

        // Initialize the COM library.
        HRESULT hr = CoInitialize(NULL);
        if (FAILED(hr))
        {
            printf("ERROR - Could not initialize COM library");
            return;
        }

        // Create the filter graph manager and query for interfaces.
        hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
                            IID_IGraphBuilder, (void **)&pGraph);
        if (FAILED(hr))
        {
            printf("ERROR - Could not create the Filter Graph Manager.");
            return;
        }

        hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
        hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

        // Build the graph. IMPORTANT: Change this string to a file on your system.
        hr = pGraph->RenderFile(s2ws(m_strFilePath).c_str(), NULL);
        if (SUCCEEDED(hr))
        {
            // Run the graph.
            hr = pControl->Run();
            if (SUCCEEDED(hr))
            {
                // Wait for completion.
                long evCode;
                pEvent->WaitForCompletion(INFINITE, &evCode);

                // Note: Do not use INFINITE in a real application, because it
                // can block indefinitely.
            }
        }
        pControl->Release();
        pEvent->Release();
        pGraph->Release();
        CoUninitialize();
    }

};

int main(void)
{
    MusicPlayer A;
    A.playAudio("music.mp3");
    system("pause");
    return 0;
}

5 个答案:

答案 0 :(得分:5)

你不能运行一个对象!您可以运行的是特定对象的成员函数:std::thread需要被告知线程的入口函数。它使用第一个构造函数参数作为函数对象,并将所有其他参数作为如何调用函数的参数。由于您的类没有函数调用运算符,std::thread不知道要调用哪个函数。

有一些方法可以解决问题:

  1. 您为operator()()类型提供函数调用MusicPlayer作为线程的输入函数。
  2. 您使用成员函数作为第一个参数以及实际对象作为传递的参数,例如std::thread t1(&MusicPlayer::test, &A)
  3. 您使用易于绑定的函数对象作为std::thread的参数,例如std::thread t1(std::bind(&MusicPlayer::test, std::ref(A))

答案 1 :(得分:2)

好的我已经解决了我的问题,它出现了std :: thread非常适合在后台播放mp3文件,感谢std :: thread。注意: audioThread(&amp; MusicPlayer :: play_sound,this);

#include <iostream>

#pragma comment(lib, "Strmiids.lib") 

#include <thread>
#include <dshow.h>
#include "Lib/NSL.h"

typedef enum MusicStatus {
    MUSIC_PLAYING = 0, 
    MUSIC_PAUSED, 
    MUSIC_STOPPED, 
    MUSIC_IDLE
} MusicStatus, *pMusicStatus;

class MusicPlayer
{
public:

    MusicPlayer() {

        m_bIsPlaying = false;
        m_bIsPaused = false;
        m_bIsStopped = false;
        m_pControl = NULL;
        m_pEvent = NULL;
        m_pGraph = NULL;
        m_pEventEx = NULL;
        m_pBasicAudio = NULL;
        m_pMediaSeeking = NULL;

        // Initialize the COM library
        m_hr = CoInitialize(NULL);
        if (FAILED(m_hr)) { // Could not initialize COM library");
            return;
        }

        // Create the filter graph manager and query for interfaces.
        m_hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGraph);

        if (FAILED(m_hr)) { // Could not create the Filter Graph Manager
            return;
        }

        m_hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **)&m_pControl);
        m_hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **)&m_pEvent);
        m_hr = m_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&m_pEventEx);
        m_hr = m_pGraph->QueryInterface(IID_IBasicAudio, (void**)&m_pBasicAudio);
        m_hr = m_pGraph->QueryInterface(IID_IMediaSeeking, (void**)&m_pMediaSeeking);
    }

    ~MusicPlayer() {
        m_pControl->Release();
        m_pEvent->Release();
        m_pEventEx->Release();
        m_pGraph->Release();
        m_pBasicAudio->Release();
        m_pMediaSeeking->Release();
        CoUninitialize();
    }

    bool isPaused() {
        return m_bIsPaused;
    }

    bool isPlaying() {
        return m_bIsPlaying;
    }

    MusicStatus getState() {
        if ( !m_bIsPlaying && !m_bIsPaused && !m_bIsStopped )
            return MUSIC_IDLE;
        if ( m_bIsPlaying )
            return MUSIC_PLAYING;
        if ( m_bIsPaused ) 
            return MUSIC_PAUSED;
        if ( m_bIsStopped )
            return MUSIC_STOPPED;
        return MUSIC_STOPPED;
    }

    void playAudio(std::string strFilePath) {
        m_strFilePath = strFilePath;
        set_state(MUSIC_PLAYING);
        std::thread audioThread(&MusicPlayer::play_sound, this);
        audioThread.join();
    }

    bool stopAudio() {
        if ( getState() == MUSIC_PLAYING && m_pControl ) {
            m_hr = m_pControl->Stop();
            if ( SUCCEEDED(m_hr) ) {
                set_state(MUSIC_STOPPED);
                return true;
            }
        }
        return false;
    }

    bool pauseAudio() {
        if ( getState() == MUSIC_PLAYING && m_pControl ) {
            return SUCCEEDED(m_pControl->Pause());
        }
        return false;
    }

    long volume() {
        if ( m_bIsPlaying && m_pBasicAudio ) {
            long lVolume = -1;
            m_hr = m_pBasicAudio->get_Volume(&lVolume);
            if ( SUCCEEDED(m_hr) )
                return lVolume;
        }
        return -1;
    }

    bool setVolume(long lVolume) {
        if ( m_bIsPlaying && m_pBasicAudio ) {
            m_hr = m_pBasicAudio->put_Volume(lVolume);
            return SUCCEEDED(m_hr);
        }
        return false;
    }

    long durationInSeconds() {
        return m_ulTrackDuration / 10000000;
    }

    __int64 currentPosition() {
        if ( getState() == MUSIC_PLAYING && m_pMediaSeeking ) {
            __int64 curPosition = -1;
            m_hr = m_pMediaSeeking->GetCurrentPosition(&curPosition);
            if ( SUCCEEDED(m_hr) )
                return curPosition;
        }
        return -1;
    }

    bool setPosition(__int64* pCurrentPos, __int64* pStop, bool bAbsolutePositioning) {
        if ( getState() == MUSIC_PLAYING && m_pMediaSeeking ) {
            DWORD flags = 0;
            if ( bAbsolutePositioning )
                flags = AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame;
            else
                flags = AM_SEEKING_RelativePositioning | AM_SEEKING_SeekToKeyFrame;
            m_hr = m_pMediaSeeking->SetPositions(pCurrentPos, flags, pStop, flags);
            if ( SUCCEEDED(m_hr) )
                return true;
        }
        return false;
    }

private:

    bool m_bIsPlaying, m_bIsPaused, m_bIsStopped;
    std::string m_strFilePath;

    HRESULT m_hr;
    IGraphBuilder *m_pGraph;
    IMediaControl *m_pControl;
    IMediaEvent   *m_pEvent;
    IMediaEventEx *m_pEventEx;
    IBasicAudio   *m_pBasicAudio;
    IMediaSeeking *m_pMediaSeeking;

    // 10,000,000 per second
    __int64 m_ulTrackDuration;

    void set_state(MusicStatus m) {
        switch(m) {
        case MUSIC_STOPPED:
            m_bIsStopped = true;
            m_bIsPlaying = m_bIsPaused = false;
            break;
        case MUSIC_PAUSED:
            m_bIsPaused = true;
            m_bIsPlaying = m_bIsStopped = false;
            break;
        case MUSIC_PLAYING:
            m_bIsPlaying = true;
            m_bIsPaused = m_bIsStopped = false;
            break;
        case MUSIC_IDLE:
            m_bIsPaused = m_bIsPlaying = m_bIsStopped = false;
            break;
        }
    }

    void play_sound() {
        m_hr = m_pGraph->RenderFile(s2ws(m_strFilePath).c_str(), NULL);
        if (SUCCEEDED(m_hr))
        {
            m_hr = m_pControl->Run();
            if (SUCCEEDED(m_hr)) {
                if ( m_pMediaSeeking ) {
                    m_pMediaSeeking->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);
                    m_pMediaSeeking->GetDuration(&m_ulTrackDuration);
                }
            }
        }

    }

};

int main(void)
{
    MusicPlayer A;
    A.playAudio("music.mp3");
    std::cout << A.durationInSeconds();
    system("pause");
    return 0;
}

答案 2 :(得分:1)

使用std::thread作为MusicPlayer类的成员,并通过将线程函数分配给它尽快更改为状态MUSIC_PLAYING来启动后台线程。

答案 3 :(得分:1)

小问题:

MusicPlayer(void)
bool isPaused(void)
bool isPlaying(void)

零参数的函数定义为:

MusicPlayer()
bool isPaused()
bool isPlaying()

主要问题。

线程对象构造函数采用仿函数。因为你没有传递任何参数,所以仿函数也必须采用零参数。这意味着传递给线程的对象必须是可调用的,如下所示:

MusicPlayer A;
std::thread t1(A);

// This means that the object A is callable like a function.
A();

// For this to work the class MusicPlayer must define the opropriate function operator:

class MusicPlayer
{
    public:
        void operator()() { /* Code run inside thread */ }
};

答案 4 :(得分:0)

您可以尝试类似

的内容
std::thread audioThread(([this](){MusicPlayer::play_sound();};