Conversation

How threadsafe is TBitmap

(overview of excerpts from articles in conversation)

Newsgroup: embarcadero.public.delphi.graphics

# Lines
wrote on 20-Aug-2009:

I am trying to parallellize bitmap operations. This appears to be well
possible for scanlines. Typical code reads like this:


s := source_bitmap.Scanline [index];
29
  
Remy Lebeau (TeamB) replied on 20-Aug-2009:

"Arnold Reinders" <✉somewhere.com> wrote in message
  news:✉forums.codegear.com...
  (snip)

Technically, nothing about it is thread-safe. You should always provide a
  lock around multi-threaded access to shared resources. But as long as
  neither bitmap is ever being resized or having its underlying handles
29
  
Erik Turner replied on 21-Aug-2009:

It's not threadsafe at all. I had a similar problem where I was rendering
  JPG streams to TBitmaps in a background thread. The problem actually occurs
  (near as I can tell) when the form is updated. It trashes any active
  TCanvas's after the refresh. Someone had posted a work-around involving
  locking the TCanvas, etc but they didn't solve the problem completely. The
65
  
Alex Belo replied on 21-Aug-2009:

See
  Report #: 43020 Status: Reported
  TBitmap.Canvas.Lock is a MUST in multithreading applications
  http://qc.embarcadero.com/wc/qcmain.aspx?d=43020
  Jan Derk:
23
    
Arnold Reinders replied on 21-Aug-2009:

Hi Alex, Erik, Remy,
    Thanks very much for your answers.
    Alex Belo wrote:
    (snip)

Thanks for the pointer.
    (snip)

When I understand Alex and Erik correctly I must be careful not to
55
  
Jens Gruschel replied on 21-Aug-2009:

(snip)

TBitmap itself is not thread-safe. However the (DIB) pixel data can be accessed
  from various threads without problems, after all it's just some memory block. Of
  course your algorithm itself must be synchronized, for example if several
  threads are accessing the same pixel (it's no problem if each thread works on a
  different slice of the pixel data, or if all threads only read from the pixel
67
  
David HAROUCHE replied on 22-Aug-2009:

Better use a private TBitmap to the thread, and give public access to a
  built-shadow TBitmap of it via a property of the Thread....
  DH
  
  
5
    
Jens Gruschel replied on 22-Aug-2009:

(snip)

Yes, generally threads using private variables only are easier to handle
    (combining their results in a synchronized method). But sometimes there are good
    reasons for sharing data among different threads. Let's say a low pass filter,
    where each thread generates a separate section of a result image, but needs to
    read pixels from the whole area of a shared source image (well, one could
29
  
Alex Belo replied on 22-Aug-2009:

Arnold Reinders wrote:
  (snip)

I don't know _exactly_.
  Mr. Bauer, would you please help us.
  (snip)

You definitely must do it via Sinchronize.
  (snip)

You definitely must do it (any drawing on form) via Sinchronize too. So
30
  
Erik Turner replied on 23-Aug-2009:

Comments inline.
  "Arnold Reinders" <✉somewhere.com> wrote in message
  news:✉forums.codegear.com...
  (snip)

As another poster mentioned, you MAY be able to get this to work if you
  call ScanLine in the main/GUI thread and pass the scan line addresses to
58
    
Jan Derk replied on 23-Aug-2009:

David HAROUCHE wrote:
    (snip)

That is not correct. The really confusing part is that even local TBitmap are
    not thread safe unless you lock them.
    This is because every TBitmap registers itself to the global BitmapCanvasList
    list in graphics.pas. And when the DC garbage collection FreeMemoryContexts()
26
  
David HAROUCHE replied on 24-Aug-2009:

(snip)
This sounds obvious when working with concurrent processes !
  DH
  ✉hotmail.fr
  
  
8
    
Jan Derk replied on 24-Aug-2009:

David HAROUCHE wrote:
    (snip)



What I meant is that TBitmaps that are declared private to a thread aren't so
    private, because they register themselves in a global list which is accessed by
    the garbage collector in the mean thread.
    Normally locking is only required if an object can be accessed by multiple
32
  
Alex Belo replied on 24-Aug-2009:

In the end I would like to know for sure: do I have to do Canvas.Lock
  when I use Scanline only, or such the lock is unnecessary?
  --
  Alex
  
5
    
Jan Derk replied on 24-Aug-2009:

Alex Belo wrote:
    (snip)

Yes, you have to lock it if you use it in a thread.
    Jan Derk
    
    
8
  
Alex Belo replied on 24-Aug-2009:

Jan Derk wrote:
  (snip)

Thank you Jan.
  --
  Alex
  
11
  
Alex Belo replied on 24-Aug-2009:

Does the lock affect negatively on other threads?
  --
  Alex
  
  
2
    
Jan Derk replied on 24-Aug-2009:

Alex Belo wrote:
    (snip)
No. It just prevents the DC garbage collector from deleting the device context
    of the canvas.
    Jan Derk
    
7
  
Alex Belo replied on 24-Aug-2009:

Jan Derk wrote:
  (snip)
OK, as I suspected.
  Thank you again.
  --
  Alex.
3
  
Sergio Gianezini replied on 31-Aug-2009:

TBitmap.Canvas suffer from same issue that I have when trying to use
  ShowMessage() - TForm.Canvas - in a multithread application.
  This piece of code in dialog.pas causes randomly AV's, 'cause the Canvas DC
  get's freed by main thread.
  function GetAveCharSize(Canvas: TCanvas): TPoint;
53
    
Alex Belo replied on 31-Aug-2009:

Sergio Gianezini wrote:
    (snip)

ShowMessage dialog is VCL form. So you can't use it in secondary
    thread(s). To show your short modal messages use WinAPI dialogs instead.
    --
    Alex
12
  
Jens Gruschel replied on 05-Sep-2009:

(snip)
Actually you don't have to lock it, if you make sure no canvas is accessed while
  your threads are executed. So your main thread should be blocked during your
  operation (for example using WaitForMultipleObjects). But it's no problem to
  have any number of threads working on one or more bitmaps without locking, if
  you are only accessing the memory given by the scanline property.
19
    
Alex Belo replied on 06-Sep-2009:

Jens Gruschel wrote:
    (snip)

So we have 2 different POV on this problem now. :-)
    Really, I'd like to see an official POV.
    --
    Alex
9
  
Jens Gruschel replied on 06-Sep-2009:

(snip)
Officially you have to lock bitmaps, but not if the main thread is blocked :-)
  The explanation is simple: you have to lock bitmaps unless you make sure
  FreeDeviceContexts is never called, which happens in TWinControl.DestroyWnd and
  TWinControl.MainWndProc. But these methods are only executed while the main
  (GUI) thread is active (processes messages etc.). I'd also avoid accessing any
55
    
Alex Belo replied on 07-Sep-2009:

Jens Gruschel wrote:
    Thank you Jens for input.
    (snip)

....
    (snip)

Very special case. Freezing GUI is not acceptable.
    ---
41
  
Jens Gruschel replied on 07-Sep-2009:

(snip)
It's not so special if you want to execute an image processing operation on a
  multi core machine and wait for the result in the main thread, something like
  (pseudo code):
  StartThreads(GetNumberOfProcessors);
  WaitForThreads;
19
    
Alex Belo replied on 08-Sep-2009:

Jens Gruschel wrote:
    (snip)

In other words stop main thread (GUI). As I aldeady said:
    (snip)

OK, thank you for explanation.
    --
    Alex
23
  
Earik Beann replied on 02-Nov-2009:

Hey Guys,
  FYI, I solved my bitmap thread issues by swapping out Graphics::TBitmap for TBitmap32, which is an open source bitmap replacement for Delphi/C++ Builder that doesn't suffer from these issues. www.graphics32.org if you're curious. I spent weeks trying to make it work with the standard class, but just couldn't get it going...
  Earik
  
  
14
FYI: Phrase searches are enclosed in either single or double quotes
 
 
Originally created by
Tamarack Associates
Sun, 12 May 2024 22:02:43 UTC
Copyright © 2009-2024
HREF Tools Corp.