Я поддерживаю приложение Delphi 10.2.3 Isapi, которое использует FMX.Graphics.TBitmap. Несколько потоков создают свое собственное личное растровое изображение, рисуют его, возвращают двоичный контент в обработчик веб-запроса и освобождают растровое изображение. Во время отладки нарушения доступа происходят в этой трассировке стека:
:760c4742 KERNELBASE.RaiseException + 0x62
System.DynArraySetLength(nil,$407163,16,$F)
System.DynArraySetLength($6113648,$5DDE84,1,$6B6FE78)
System.Generics.Collections.TListHelper.InternalSetCapacity(8514146)
System.Generics.Collections.TListHelper.InternalGrow(???)
System.Generics.Collections.TListHelper.InternalGrowCheck(???)
System.Generics.Collections.TListHelper.InternalAddManaged((no value))
System.Messaging.TMessageManager.SubscribeToMessage(???,(FMX.Canvas.D2D.TCanvasD2D.ContextLostHandler,$6122F70))
FMX.Canvas.D2D.TCanvasD2D.CreateFromBitmap(???,SystemDefault)
FMX.Graphics.TBitmap.GetCanvas
Unit1.TWorker.Execute
Я подозреваю, что этот код в коде структуры FMX не является потокобезопасным:
// FMX.Canvas.D2D.pas:
constructor TCanvasD2D.CreateFromBitmap(const ABitmap: TBitmap; const AQuality: TCanvasQuality);
begin
inherited;
FLastBrushTransform := TMatrix.Identity;
CreateResources;
FContextLostId := TMessageManager.DefaultManager.SubscribeToMessage(TContextLostMessage, ContextLostHandler);
end;
Он вызывает singleton TMessageManager.DefaultManager и добавление обработчика во внутренний словарь без какой-либо блокировки. Это не выглядит очень безопасным. Согласно документации, растровые изображения FMX могут использоваться в потоках при использовании BeginScene и EndScene, что нормально. Но на самом деле создание / уничтожение холста FMX не кажется потокобезопасным из-за подписки / отмены подписки на одноэлементный MessageManager по умолчанию? Является ли это предположение правильным?
Странно то, что оно может вызывать нарушения прав доступа только тогда, когда какой-либо код был приостановлен и возобновлен где-то в отладчике через точку останова. Когда программа никогда не останавливается на точках останова, она запускается без проблем.