如何使用c ++中的winapi事件解决Producer-Consumer问题?

时间:2017-04-03 20:17:30

标签: c++ winapi synchronization

我需要使用原始同步对象解决c ++中的Producer-Consumer问题 - 事件,我已经编写了这段代码

static int g_x = 0;
HANDLE hEvent1;

HANDLE aThread[2];
DWORD ThreadID;

//tread 1
void Producer()
{
    for (int i = 0; i < 100; ++i)
    {
        WaitForSingleObject(hEvent1, INFINITE);
        g_x = i;
        SetEvent(hEvent1);
    }
}
//thread 2
void Consumer()
{
    for (;;)
    {
        WaitForSingleObject(hEvent1, INFINITE);
        SetEvent(hEvent1);
    }
}

int createthreads() {
    hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL);

    // Create worker threads
    aThread[0] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Producer, NULL,  0, &ThreadID);
    aThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer, NULL, 0, &ThreadID);
}
int main() {
    createthreads();
}

此代码无法正常工作:我有无限循环 如何修复此代码以获取从099的控制台号码?

2 个答案:

答案 0 :(得分:1)

您需要另一个事件来同步这两个线程。 另外,我将两个事件的初始状态设置为FALSE,然后将一个启动事件发送到main上的生产者线程。 这样您就可以控制进程的启动时间和方式。

Offtopic,createthreads必须返回一个值。

static int g_x = 0;
HANDLE hEvent1;
HANDLE hEvent2;

HANDLE aThread[2];
DWORD ThreadID;

//tread 1
void Producer()
{
    for (int i = 0; i < 100; ++i)
    {
        WaitForSingleObject(hEvent1, INFINITE);
        g_x = i;
        SetEvent(hEvent2);
    }
}
//thread 2
void Consumer()
{
    for (;;)
    {
        WaitForSingleObject(hEvent2, INFINITE);
        SetEvent(hEvent1);
    }
}

int createthreads() {
    hEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL);
    hEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL);

    // Create worker threads
    aThread[0] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)Producer, NULL,  0, &ThreadID);
    aThread[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer, NULL, 0, &ThreadID);
    return 0;
}
int main() {
    createthreads();
    SetEvent(hEvent1);
}

答案 1 :(得分:0)

存在许多实现此任务的方式,一种可能 - 需要使用事件对--2个事件。

struct EventPair 
{
    HANDLE hLowEvent, hHighEvent;

    ~EventPair()
    {
        if (hHighEvent) CloseHandle(hHighEvent);
        if (hLowEvent) CloseHandle(hLowEvent);
    }

    EventPair()
    {
        hLowEvent = 0, hHighEvent = 0;
    }

    DWORD Create()
    {
        return (hLowEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) &&
            (hHighEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) ? NOERROR : GetLastError();
    }
};

struct SharedData : EventPair 
{
    int _x;
    bool _quit;

    SharedData()
    {
        _x = 0;
        _quit = false;
    }

    static DWORD WINAPI _Producer(void* This)
    {
        reinterpret_cast<SharedData*>(This)->Producer();
        ExitThread(0);
    }

    void Producer()
    {
        for (int i = 0; ; )
        {
            _x = i++;
            if (i == 100)
            {
                _quit = true;
            }
            SetEvent(hLowEvent);
            if (_quit)
            {
                return;
            }
            WaitForSingleObject(hHighEvent, INFINITE);
        }
    }

    static DWORD WINAPI _Consumer(void* This)
    {
        reinterpret_cast<SharedData*>(This)->Consumer();
        ExitThread(0);
    }

    void Consumer()
    {
        for(;;) 
        {
            WaitForSingleObject(hLowEvent, INFINITE);
            DbgPrint("%u\n", _x);
            if (_quit)
            {
                return;
            }
            SetEvent(hHighEvent);
        }
    }
};

void testPC()
{
    SharedData sd;
    if (!sd.Create())
    {
        HANDLE hThreads[2] = {};
        if (hThreads[0] = CreateThread(0, 0, SharedData::_Producer, &sd, 0, 0))
        {
            if (hThreads[1] = CreateThread(0, 0, SharedData::_Consumer, &sd, 0, 0))
            {
                WaitForMultipleObjects(2, hThreads, TRUE, INFINITE);
                CloseHandle(hThreads[1]);
            }
            else
            {
                sd._quit = true;
                SetEvent(sd.hHighEvent);
                WaitForSingleObject(hThreads[0], INFINITE);
            }
        }
        CloseHandle(hThreads[0]);
    }
}
相关问题