在各自的线程上运行多个对象似乎多次运行同一个对象

时间:2012-11-14 22:15:04

标签: c++ multithreading oop winapi object

我正在尝试创建一个类的12个新实例并运行它们中的每一个它是一个自己的线程,但它们接缝以共享相同的数据。 所有12个实例都位于相同的X和Y位置,但它们每个都应该在随机方向上移动。 正如你在代码中看到的那样,我尝试了各种各样的apraoches,但我找不到原因。

我在这里做错了什么?

P.S。是的...我知道还有一些未使用的变量。 在我发布问题之前,我已经看过很多地方了。

enemy.cpp

#include "enemy.h"
#include <time.h>
#include <windows.h>



FILE* pEnemyFile = fopen ("enemylog.txt","w");

Enemy::Enemy(const MouseServer& mServer, int& lastMousePosX, int& lastMousePosY, int& winSizeX, int& winSizeY )
    :mouseServer(mServer),
    lastMouseX( ( lastMousePosX ) ? lastMousePosX : 0 ), // evaluate if we get the reference
    lastMouseY( ( lastMousePosY ) ? lastMousePosY : 0 ),
    myPositionX(0),
    myPositionY(0),
    winSizeX(winSizeX),
    winSizeY(winSizeY),
    x(0),
    y(0)
{
    // original source:
    // http://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx
    // Allocate memory for thread data.
    EDATA threadEnemyData = (EDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,sizeof(enemyData));


    // http://www.codeproject.com/Articles/14746/Multithreading-Tutorial
    // http://www.codeguru.com/cpp/w-d/dislog/win32/article.php/c9823/Win32-Thread-Synchronization-Part-I-Overview.htm

    // usefull information
    // http://msdn.microsoft.com/en-us/library/z3x8b09y(v=vs.100).aspx

     if( threadEnemyData == NULL )
     {
         //If the array allocation fails, the system is out of memory
         //so there is no point in trying to print an error message.
         //Just terminate execution.
         ExitProcess(2);
     }


    threadEnemyData->X = 0;
    threadEnemyData->Y = 0;

    this->hThread = CreateThread( 
        NULL, 
        0, 
        this->MyThreadFunction,
        this,
        /*threadEnemyData,*/
        0,
        &this->dwThreadID
    );


        // Check the return value for success.
        // If CreateThread fails, terminate execution. 
        // This will automatically clean up threads and memory. 

        if (this->hThread== NULL) 
        {
           ErrorHandler(TEXT("CreateThread"));
           ExitProcess(3);
        }
        //End of main thread creation loop.
}

Enemy::~Enemy()
{
    // Wait until all threads have terminated.
    WaitForSingleObject(this->hThread,INFINITE);

    // Close all thread handles and free memory allocations.
    this->hDefaultProcessHeap = GetProcessHeap();
    if (this->hDefaultProcessHeap == NULL) {
    }


    CloseHandle(this->hThread);
    //if(threadEnemyData != NULL)
    //{
    //  HeapFree(GetProcessHeap(), 0, threadEnemyData);
    //  hThread = NULL;    // Ensure address is not reused.
    //}

    // close debug file
    fclose (pEnemyFile);
}

void Enemy::Draw(D3DGraphics& gfx)
{
    gfx.PutPixel(this->x + 0,this->y,255,255,255);
    gfx.PutPixel(this->x + 1,this->y,255,255,255);
    gfx.PutPixel(this->x + 2,this->y,255,255,255);
    gfx.PutPixel(this->x + 3,this->y,255,255,255);
    gfx.PutPixel(this->x + 4,this->y,255,255,255);
    gfx.PutPixel(this->x + 5,this->y,255,255,255);
    gfx.PutPixel(this->x + 6,this->y,255,255,255);
    gfx.PutPixel(this->x + 7,this->y,255,255,255);
}

// read
// http://www.tek-tips.com/viewthread.cfm?qid=1068278
DWORD WINAPI Enemy::MyThreadFunction( void* param ) 
{ 
    Enemy* self = (Enemy*) param;
    ////self->  // <-- "this"
    return self->NewThread();
}

  /* initialize random seed: */


// the itelligence loop of your enemy/object
DWORD Enemy::NewThread()
{
    do
    {
        srand ( time(NULL) );
        /* generate random number: */
        //self->x += rand() % 4;
        //self->y += rand() % 4;
        this->x += rand() % 4;
        this->y += rand() % 4;


        // debug stuff
        char buffer[ 64 ];
        sprintf_s(buffer, "enemy:   x:   %d Y: %d id: %d\n", (char)this->x,  (char)this->y, (char)this->dwThreadID);
                fputs (buffer,pEnemyFile);

        // allow processor time to other threads
        Sleep(100);
    }while(true);  // endles loop
}

void Enemy::ErrorHandler(LPTSTR lpszFunction) 
{ 
    // Retrieve the system error message for the last-error code.
    this->dw = GetLastError(); 
    // todo
}

enemy.h

#pragma once

#include "timer.h"
#include "D3DGraphics.h"
#include "D3DGraphics.h"
#include "Mouse.h"

/////// thread stuf
#include <tchar.h>
#include <strsafe.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


class Enemy
{
public:
    Enemy();
    Enemy(const MouseServer& mServer, int& lastMousePos, int& lastMousePosY, int& winSizeX, int& winSizeY);
    ~Enemy();

    static DWORD WINAPI MyThreadFunction( LPVOID lpParam );
    DWORD Enemy::NewThread();
    void ErrorHandler(LPTSTR lpszFunction);

    void lookingForFood();
    void Draw(D3DGraphics& gfx);
    int Enemy::correctX(int xParam);
    int Enemy::correctY(int yParam);

private:
    int myPositionX;
    int myPositionY;
    int lastMouseX; 
    int lastMouseY;
    int winSizeX;
    int winSizeY;
    //int moveToX;  // todo
    //int moveToY;

    int x;
    int y;


    // threading stuff
    typedef struct ENEMYDATA // don't forget "typedef "
    {
        int X;
        int Y;  // test
    } enemyData, *EDATA;

    // Cast the parameter to the correct data type.
    // The pointer is known to be valid because 
    // it was checked for NULL before the thread was created.
    static Enemy* self;
    HANDLE  hThread;
    DWORD   dwThreadID;
    HANDLE hDefaultProcessHeap;
    DWORD dw; // error message

    EDATA* threadEnemyData;

    MouseClient mouseServer;
    //D3DGraphics& grafix;
    Timer timer;
};

1 个答案:

答案 0 :(得分:5)

它在你的线程过程中被注释掉,但看起来你是在正确的轨道上:

srand(time(NULL));

它不适合你,因为所有线程都开始如此之快以至于它们以时间(NULL)结束为每个线程返回相同的值。这意味着他们都使用相同的随机序列。尝试使用线程ID(或每个线程唯一的其他源)播种rand,你应该看到唯一的伪随机数序列。