我具有以下功能:
void Class1::MainThreadFunction(const __int64 param) {
if(GetCurrentThreadId() != System::MainThreadID) {
RunInMainThread(MainThreadFunction, param);
return;
}
//...
}
void Class2::RunInMainThread(void(__closure* FuncToCall)(const __int64 ParToExtract),
const __int64 fP1) {
struct {
__int64 P1;
void(__closure* F)(const __int64);
void __fastcall FTC() { F(P1); }
} Args = {fP1, FuncToCall};
TThread::Synchronize(NULL, &Args.FTC);
}
所以我想做的是提取FuncToCall
中的第一个参数,该参数上面名为ParToExtract
,用于初始化Args
结构。换句话说,结构中的P1
应该从名为const __int64
的传递函数中接收ParToExtract
。
以上方法有效,但我目前作为一种解决方法,将参数fP1
用作初始化P1
的参数,但是肯定有更好的方法可以实现此目的。
额外的好处是可以在RunInMainThread
中使用可变数量的函数参数(但是我暂时不使用C ++ 11 <functional>
)。
请不要使用基于lambda的功能(或C ++ 11功能)-这是我暂时无法使用的另一件事。
答案 0 :(得分:3)
由TThread::Synchronize()
调用的方法的签名必须与TThreadMethod
类型匹配:
void __fastcall (__closure *TThreadMethod)(void);
因此您不能直接通过它传递参数。不用通过代理功能,而是使用lambda:
void MainThreadFunction(int64_t param) {
if(GetCurrentThreadId() != System::MainThreadID)
TThread::Synchronize(nullptr, [¶m]{ MainThreadFunction(param); } );
//...
}
为了具有可变数量的参数,可以将其设为功能模板:
template< class... Args >
void MainThreadFunction(Args&&... args) {
if(GetCurrentThreadId() != System::MainThreadID)
TThread::Synchronize(nullptr, [&args...] {
MainThreadFunction(std::forward<Args>(args)...);
}
);
//...
}
使用经典(C ++ 11之前的版本)编译器时,通常会使用类私有变量来携带信息。
答案 1 :(得分:3)
您已经拥有的是在C ++ Builder的“经典”(C ++ 11之前的版本)编译器中解决这种情况的正确(唯一方法)。
为了支持可变数量的参数,您将不得不使用多个重载,没有其他选择(无需深入研究低级内联汇编以手动设置调用堆栈,但是即使如此,它在整个过程中也可能无法正常工作线程边界),例如:
void Class1::MainThreadFunction()
{
if (GetCurrentThreadId() != System::MainThreadID)
{
RunInMainThread(MainThreadFunction);
return;
}
//...
}
void Class1::MainThreadFunction(const __int64 param)
{
if(GetCurrentThreadId() != System::MainThreadID)
{
RunInMainThread(MainThreadFunction, param);
return;
}
//...
}
// and so on as needed ...
template<typename FuncType>
void Class2::RunInMainThread(FuncType FuncToCall)
{
struct {
FuncType F;
void __fastcall FTC() { F(); }
} Args = {FuncToCall};
TThread::Synchronize(NULL, &Args.FTC);
}
template<typename FuncType, typename ParamType>
void Class2::RunInMainThread(FuncType FuncToCall, const ParamType param)
{
struct {
const ParamType &P;
FuncType F;
void __fastcall FTC() { F(P); }
} Args = {param, FuncToCall};
TThread::Synchronize(NULL, &Args.FTC);
}
template<typename FuncType, typename ParamType1, typename ParamType2>
void Class2::RunInMainThread(FuncType FuncToCall, const ParamType1 param1, const ParamType2 param2)
{
struct {
const ParamType1 &P1;
const ParamType2 &P2;
FuncType F;
void __fastcall FTC() { F(P1, P2); }
} Args = {param1, param2, FuncToCall};
TThread::Synchronize(NULL, &Args.FTC);
}
// and so on as needed...
如果您浏览各种RTL头文件,例如sysvari.h
和utilcls.h
,则Borland本身将如何使用重载来解决多个API中变量数量可变的问题,有时甚至超过30多个参数,足以处理大多数用户代码。