我的问题是,我实例化了两个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