Как синхронизировать код в TIdTCPServer :: Execute - PullRequest
0 голосов
/ 04 мая 2018

У меня есть код VCL в методе TIdTCPServer :: Execute, который необходимо синхронизировать, как я могу это сделать?

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); 
  }
}

Код не удивительно периодически блокируется.

1 Ответ

0 голосов
/ 04 мая 2018

Ничего в этом коде не нужно делегировать основному потоку пользовательского интерфейса через Synchronize.

Однако при использовании TCanvas в рабочем потоке вам необходимо Lock(), пока вы его используете, иначе основной поток пользовательского интерфейса будет мешать ему в фоновом режиме ( ОБНОВЛЕНИЕ: в частности, основной поток пользовательского интерфейса часто выпускает HDC s, принадлежащие разблокированным TBitmap.Canvas и TControlCanvas объектам, даже тем, которые используются рабочими потоками. Вы в порядке, если вы но используйте TCanvas сам).

В качестве альтернативы просто замените TCanvas соответствующими вызовами функций Win32 API (CreateFontIndirect(), GetTextExtentPoint32()), тогда вам не нужно беспокоиться о блокировка чего угодно.

...