如何在 TIdTCPServer::Execute 中同步代码

How To Sychronize Code In TIdTCPServer::Execute

我在 TIdTCPServer::Execute 方法中有 VCL 代码需要同步,我该怎么做?

void __fastcall Tdata::bcServerExecute(TIdContext *AContext)
{
  String json = AContext->Connection->Socket->ReadLn();
  TJSONObject* jo = (TJSONObject*)TJSONObject::ParseJSONValue(json);
  if (jo != 0)
  {
    TJSONPair* jp = (TJSONPair*)jo->Get("text");
    String text = jp->JsonValue->Value();

    jp = (TJSONPair*)jo->Get("font_size");
    int font_size = _wtoi(jp->JsonValue->Value().c_str());

    int tw = 0;
    double text_width = 0.0;
    //================================
    TCanvas* canvas = new TCanvas();
    if (canvas)
    {
      canvas->Handle = GetDC(0);
      canvas->Font->Size = font_size;
      tw = canvas->TextWidth(text);
      double ppi = Screen->PixelsPerInch;
      text_width = double(tw) / ppi;
      ReleaseDC(0,canvas->Handle);

      delete canvas;
    }
    String buf = String(text_width);
    //==================================
    AContext->Connection->IOHandler->WriteLn(buf); 
  }
}

代码周期性死锁不足为奇。

此代码中的任何内容都不需要通过 Synchronize 委托给主 UI 线程。

但是,当在工作线程中使用 TCanvas 时,您确实需要在使用它时 Lock() 它,否则主 UI 线程会干扰它后台(更新: 具体来说,主要 UI 线程经常释放 HDC 属于 unlocked TBitmap.CanvasTControlCanvas 对象,甚至是工作线程正在使用的对象。不过,如果您使用 TCanvas 本身就可以了。

或者,只需将 TCanvas 替换为相应的 Win32 API 函数调用 (CreateFontIndirect(), GetTextExtentPoint32()),那么您就不必担心锁定任何内容。