我的問題是,我實例化了兩個TThread(來自Borland C++ VCL)。 他們的構造函數都成功了。 但只有第一個TThread被執行。 (這個代碼的目標是在紋理對象列表中加載大約100個PNG圖像文件;這些紋理對象(TMyObject)有一個「LoadFromFile」函數,該函數持續大約60個刻度)。兩個TThreads成功構建,但只有第一個被執行
我瀏覽過很多關於多線程的解釋,因此有:
- 試圖構建TMyThread爲已暫停(:TThread類(真)),並呼籲恢復()爲每一個
- 試圖使用TCriticalSection,或者CRITICAL_SECTION, (首先作爲TMyThread的成員...,然後作爲TMainObject的成員,指向它的指針傳遞給每個TMYThread ...,然後作爲在TMainObject側聲明的全局變量, TMyThread)
- 試圖在成員的聲明中添加__thread的TMainObject傳遞給每個TMyThread
- 試圖呼叫應用 - > ProcessMessages()中的每個TMyThread構造和執行功能
- 試圖用「布爾*」傳遞給每個TMyThread以鎖定和解鎖所述公共存儲器訪問
- 沒能成功申報一個std ::互斥
- 試着撥打同步(NULL,NULL,0,0)的臨界內存纔能有在這些操作
- 嘗試重新連接到主線程線程訪問之前每個線程使用兩對不同的列表
- 發現了這個有趣的,但需要幫助實現它: http://delphi.about.com/gi/o.htm?zi=1/XJ&zTi=1&sdn=delphi&cdn=compute&tm=41&f=00&tt=14&bt=0&bts=1&zu=http%3A//www.midnightbeach.com/jon/pubs/MsgWaits/MsgWaits.html
- 這也: http://delphi.about.com/od/kbthread/a/threaded-delphi-tasks-thread-pool-otl-omnithreadlibrary-example.htm
- 閱讀有關OTL和ASyncCalls這裏: How Do I Choose Between the Various Ways to do Threading in Delphi?
=>在所有這些嘗試沒有成功。
下面是我試圖簡化的代碼。 任何幫助或解釋將有助於我的第二個線程被執行。
//---------------------------------------------------------------------------
class TMainClass
{
private:
TMyList<SmartPtr<TEvent> > mEventList;
SmartPtr<TMyThread> mThread1, mThread2;
int mCount;
protected:
int mCurrent, mLast;
TMyList<SmartPtr<TMyObject> > mObjectList;
TMyObject *mpObject;
void MyInit();
public:
TMainObject(TMyParentObject *parent);
virtual ~TMainObject();
virtual void PeriodicTask();
};
//---------------------------------------------------------------------------
class TMyThread : public TThread
{
TMyList<SmartPtr<TEvent> > *mpEventList;
TMyList<SmartPtr<TMyObject> > *mpObjectList;
int mStart, mEnd;
public:
TMyThread( TMyList<SmartPtr<TEvent> > *pEventList,
TMyList<SmartPtr<TMyObject> > *pObjectList,
int Start, int End);
virtual void __fastcall Execute(void);
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
TMainClass::TMainClass(TMyParentObject *parent)
{
mCount = 0;
}
TMainClass::~TMainClass()
{
if (mThread1.GetPtr() != NULL)
{
mThread1->Terminate();
mThread1 = SmartPtr<TMyThread> (NULL);
}
if (mThread2.GetPtr() != NULL)
{
mThread2->Terminate();
mThread2 = SmartPtr<TMyThread> (NULL);
}
mpObject = NULL;
mObjectList.Clear();
mEventList.Clear();
}
void TMainClass::MyInit()
{
if (mThread1.GetPtr() != NULL) return;
mObjectList.Clear();
mEventList.Clear();
mCount = GetNumberOfFiles("C:/MyPath/");
for (int i = 1; i <= mCount; i++)
{
SmartPtr<TEvent> lEvent (new TEvent(NULL, false, false, ""));
lEvent.GetPtr()->ResetEvent();
mEventList.Add(lEvent);
}
mThread1 = SmartPtr<TMyThread> (new TMyThread(&mEventList, &mObjectList, 1, floor(mCount/2.0))); // lock before that ?
mThread2 = SmartPtr<TMyThread> (new TMyThread(&mEventList, &mObjectList, floor(mCount/2.0)+1, mCount)); // lock before that ?
mCurrent = 0;
}
void TMainClass::PeriodicTask()
{
mpObject = NULL;
int lCount = mObjectList.Count();
if (lCount != 0)
{
++mCurrent;
mCurrent = min(mCurrent, lCount);
if ( mLast != mCurrent
&& mEventList[mCurrent]->WaitFor(120) != wrSignaled )
return;
mLast = mCurrent;
mpObject = mObjectList[mCurrent].GetPtr(); // lock before that ?
}
if (mpObject == NULL) return;
mpObject->MyObjectUtilisation(); // lock before that ?
}
//---------------------------------------------------------------------------
TMyThread::TMyThread( TMyList<SmartPtr<TEvent> > *pEventList, TMyList<SmartPtr<TMyObject> > *pObjectList,
int Start, int End);
:TThread(false)
{
mpEventList = pEventList; // lock before that ?
mpObjectList = pObjectList; // lock before that ?
mStart = Start;
mEnd = End;
FreeOnTerminate = false;
}
void __fastcall TMyThread::Execute(void)
{
for (int i = mStart; i <= mEnd; i++)
{
try
{
if (mpEventList != NULL && mpObjectList != NULL)
{
SmartPtr<TMyObject> pObject (new TMyObject());
pObject->LoadFromFile(i);
// common memory accesses before which I want to put a lock
mpObjectList->Insert(i,pObject);
mpEventList[i]->SetEvent();
// place where I could release this lock
}
}
catch(Exception &e)
{
ShowMessage("Exception in Execute : " + e.Message);
}
}
return;
}
乾杯, Arnaud。
你確定這兩個線程都稱他們'Execute'方法是什麼?你能通過調試器中的代碼來看看發生了什麼嗎? – 2012-04-06 17:19:21
另外,如果註釋掉其他實例創建,每個線程實例是否都可以正確運行?對於線程#2,「mStart」和「mEnd」是否有意義的值? – 2012-04-06 17:26:45
好吧,我不打算重新開發你的紋理對象,所以我不得不做一些可以加載PNG文件的其他東西。 TPngImage似乎是一個很好的選擇? – 2012-04-06 20:45:09