在 C++ Builder 中从其他线程调用 Timer 方法/修改属性

Call Timer methods / modify properties from other threads in C++ Builder

我正在尝试实现以下目标:从另一个线程调用方法或修改在主线程中创建的 TTimer 计时器的属性。

代码如下所示:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
  Timer1->Interval = 5000;

  ht=(HANDLE)_beginthread(MyThread,4096,NULL);  // My Thread
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
  static int i = 0;

  i++;

  Edit1->Text = i;
}
//---------------------------------------------------------------------------


void MyThread(void *threadparamlog)
{
  // .........  My code here

  Form1->Timer1->Enabled = true;

  // .......... My code here

  Form1->Timer1->Enabled = false;
}

可以这样直接调用吗?或者使用同步是强制性的?但是,当我尝试使用它时,出现“E2268 调用未定义函数 'Synchronize'”... 请帮忙。

Is it possible to call it like that, directly

这样做不安全。从非主 VCL 线程的线程更改主 VCL 线程中使用的 VCL 组件的状态时始终 Synchronize

您可以将 <System.Classes.hpp> 中的 static TThread::Synchronize 函数与将在主 VCL 线程中执行的 lambda 函数一起使用:

void MyThread(void *threadparamlog)
{
    // .........  Your code here

    TThread::Synchronize(TThread::CurrentThread, // or static_cast<TThread*>(nullptr)
        []{ // a lambda function
            // the code in here will be executed in the main VCL thread
            Form1->Timer1->Enabled = true;
        });

    // .......... Your code here

    TThread::Synchronize(TThread::CurrentThread, // or static_cast<TThread*>(nullptr)
        []{
            Form1->Timer1->Enabled = false;
        });
}

如果您的 C++ Builder 版本不支持 lambda,您可以手动构建类似的结构:

void __fastcall SetTimerEnabledValue(TTimer* timer, bool value)
{
    struct ManualLambda {
        TTimer* timer;
        bool    value;
        void __fastcall SetTimerValue() {
            // the code in here will be executed in the main VCL thread
            timer->Enabled = value;
        }
    };

    ManualLambda lambdaish;
    lambdaish.timer = timer;
    lambdaish.value = value;
    TThread::Synchronize(TThread::CurrentThread, // or static_cast<TThread*>(nullptr)
                         &lambdaish.SetTimerValue);
}
void MyThread(void *threadparamlog)
{
    // .........  Your code here

    SetTimerEnabledValue(Form1->Timer1, true);

    // .......... Your code here

    SetTimerEnabledValue(Form1->Timer1, false);
}