我的问题是我已经实例化了两个 TThread(来自 Borland C++ VCL)。他们的两个构造函数都成功了。但只有第一个 TThread 被执行。
(此代码的目标是在纹理对象列表中加载大约 100 个 png 图像文件;这些纹理对象 (TMyObject) 具有持续大约 60 个刻度的“LoadFromFile”函数)。
我浏览了很多关于多线程的解释,因此:
- 试图将 TMyThread 构造为 Suspended (:TThread(true)) 并为每个调用 Resume()
- 尝试使用 TCriticalSection 或 CRITICAL_SECTION,(首先作为 TMyThread ... 的成员,然后作为 TMainObject 的成员,并将指向它的指针传递给每个 TMYThread ... ,然后作为在 TMainObject 一侧声明的全局变量和 TMyThread)
- 试图在传递给每个 TMyThread 的 TMainObject 成员的声明中添加 __thread
- 尝试在每个 TMyThread 构造函数和 Execute 函数中调用 Application->ProcessMessages()
- 尝试使用传递给每个 TMyThread 的“bool *”来锁定和解锁公共内存访问
- 尝试声明 std::mutex 失败
- 尝试在关键内存访问之前调用 Synchronize(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 的信息: 如何在 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;
}
干杯,阿诺德。