2012-11-14 43 views
3

我試圖創建12個類的新實例,並運行它們中的每一個它是自己的線程,但它們縫分享相同的數據。 所有12個實例位於相同的X和Y位置,但它們每個都應該隨機移動。你可以在代碼中看到 ,我試過各種apraoches,但我找不到原因。每個在自己的線程上運行多個對象似乎多次運行相同的對象

我在這裏做錯了什麼?

p.s.是的......我知道還有一些未使用的變量。 PSS我已經看過很多地方,也是在這裏之前,我張貼的問題

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

即使構造函數尚未返回,您的'CreateThread'調用也會傳遞'this'指針。如果線程在構造函數返回之前將該指針解引用(顯然可以),該線程將訪問尚未完全構造的對象。一般來說,你不應該在構造函數中創建對象服務線程。 –

+0

我應該創建另一個函數並從構造函數中觸發它,或者讓Enemy類的Game類觸發該函數? 感謝您的回覆 – NaturalDemon

+1

我建議您在構造函數返回後調用某種'start'函數。 –

回答

5

它在你的線程PROC註釋掉了,但看起來像你在正確的軌道上:

srand(time(NULL));

它不適合你,因爲所有的線程開始如此之快以至於它們以時間(空)返回每個線程的相同值結束。這意味着他們都使用相同的隨機序列。嘗試使用線程ID(或每個線程唯一的其他來源)種子rand,並且應該看到唯一的僞隨機數序列。

+0

你在哪裏更快,我編輯我的文章之前。 我看到「srand(time(NULL));」被註釋掉並糾正它 但這不是錯誤。 – NaturalDemon

+0

omg,對不起 但你說得對 srand((unsigned int)this-> dwThreadID); 謝謝! 其他任何可以被認證的..關於線程安全性? 做的工作 – NaturalDemon