dbPicShow - proper usuage

Please post bug reports, feature requests, or any question regarding the DELPHI AREA projects here.

dbPicShow - proper usuage

Hi everyone,

I'm fairly new to Delphi and I have to say that I love the PicShow components.

However I'm running into a problem that I KNOW is my programming.

I have about 9 dbpicshow components split between three timers. Each timer timer simply moves the corresponding adoTable.NEXT until it reaches the EOF and starts over again.

Eventually and intermittently my application will crash somewhere in the pseffect.pas code. Before stepping to the NEXT record i do a dbpicshow.stop on all components which I thought might be the problem.

I believe the problems is related to threading which I am not too familiar with. Can someone perhaps give me some insight as to how I should properly accomplish this task.

thank you
kidjake28
Active Member

Posts: 11
Joined: February 26th, 2010, 3:12 am

Re: dbPicShow - proper usuage

This is where it crashes in pseffect.pas

Code: Select all
procedure Effect119(Display, Image: TBitmap; W, H, X, Y, Progress: Integer);var  dstPixel, srcPixel: PRGBQuad;  Weight: Integer;  I: Integer;begin  srcPixel := Image.ScanLine[H - 1];  dstPixel := Display.ScanLine[H - 1];  Weight := MulDiv(256, Progress, 100);  for I := (W * H) - 1 downto 0 do  begin    with dstPixel^ do    begin      Inc(rgbRed, (Weight * (srcPixel^.rgbRed - rgbRed)) shr 8);        <-------------- Crashes here      Inc(rgbGreen, (Weight * (srcPixel^.rgbGreen - rgbGreen)) shr 8);      Inc(rgbBlue, (Weight * (srcPixel^.rgbBlue - rgbBlue)) shr 8);    end;    Inc(srcPixel);    Inc(dstPixel);  end;end;
kidjake28
Active Member

Posts: 11
Joined: February 26th, 2010, 3:12 am

Re: dbPicShow - proper usuage

Obviously the problem is because of synchronization.

Calling Stop is not enough because the thread can be still working. You should use OnComplete event or check Busy property to know when the thread is actually stopped.

In other hand, having 9 threads is not efficient. It's better to use PicShow instances in manual mode, and use an external timer to advance Progress property of them manually.
Kambiz

Kambiz

Posts: 2430
Joined: March 7th, 2003, 7:10 pm

Re: dbPicShow - proper usuage

Kazmbiz,

Thank you so much for the reply. I know it can be frustrating dealing with newbs (like myself) but I do appreciate it.

I understand the checking for busy and oncomplete event however I'm not very clear on using PicShow in manual mode.

First of all I guess I don't understand the implications of having 9 dbPicshows (consequently 9 threads). Will it slow the machine, use more memory? (I know newb question)

Secondly, are you saying that I configure all dbPicShows for manual mode, then when I advance to the next record, I start a timer or loop to advance the progress property?
Like this?

for i = 1 to 100 do
begin
if not(dbPicShow1.busy) then dbPicShow1.Progress=i;
if not(dbPicShow2.busy) then dbPicShow2.Progress=i;
if not(dbPicShow1.busy) then dbPicShow3.Progress=i;
end;

BTW there is a THREADED property in dbPicShow, show this be enabled to disabled (or is it not related to what we are talking about ).
kidjake28
Active Member

Posts: 11
Joined: February 26th, 2010, 3:12 am

Re: dbPicShow - proper usuage

Any thoughts?
kidjake28
Active Member

Posts: 11
Joined: February 26th, 2010, 3:12 am

Re: dbPicShow - proper usuage

The following blog post gives you an overview about the threads and their resource usages:
http://blogs.technet.com/b/markrussinov ... 61309.aspx

If you set Threaded property of PicShow to False, it uses a timer instead of thread to advance the transition. However, using 9 timers is worse than using 9 working threads.

By PicShow in manual mode, you can use a single timer to advance transitions on as many as PicShow controls. Here I briefly describe how to use PicShow in this way. I supposed DBPicShow controls are on your MainFRM.

1. Set Manual property of all DBPicShow instances to True
2. Drop a TTimer component on the form and name it TransTimer
3. Set Interval property of the timer to 50 and its Enabled to False
4. Use the following code for OnTimer event of the timer:

Code: Select all
procedure TMainFRM.TransTimerTimer(Sender: TObject);const  Step = 2;begin  // advance transitions  for I := 0 to ControlCount - 1 do    if Controls[I] is TDBPicShow then       with TDBPicShow(Controls[I]) do Progress := Progress + Step;  // stop timer if transitions are done  TransTimer.Enabled := (dbPicShow1.Progress < 100);end;

5. Use the following procedure to move to the next table record:

Code: Select all
procedure TMainFRM.NextImageSet;var  I: Integer;begin  // stop Transition timer  TransTimer.Enabled := False;  // stop all DBPicShow instances  for I := 0 to ControlCount - 1 do    if Controls[I] is TDBPicShow then       TDBPicShow(Controls[I]).Stop;  // advance to the next record  adodb1.Next;  adodb2.Next;  adodb3.Next;  // start all DBPicShow instances  for I := 0 to ControlCount - 1 do    if Controls[I] is TDBPicShow then       TDBPicShow(Controls[I]).Execute;  // start Transition timer  TransTimer.Enabled := False;end;
Instead of TTimer, you can use a threaded timer (for example, TMultimediaTimer of Wave Audio Package).
Kambiz

Kambiz

Posts: 2430
Joined: March 7th, 2003, 7:10 pm

Re: dbPicShow - proper usuage

Thanks very much Kambiz,

With your example, I completely understand what you were referring to. Thanks for all the effort.

I have a few quick questions if you don't mind.

1) As for the 'procedure to move to the next table code'. I'd like to put this in a timer so that it waits a set amount a time before advancing to the next pic. Do I need to use a threaded timer for this or just the regular TTimer.

2) Why is is that you don't check .busy in your example? Do we not have to using this method?

3) I find that during the cycles some of the picture get missed (meaning it's doesn't display or it's 10% progress - light grey). What would cause the timer to not complete?
kidjake28
Active Member

Posts: 11
Joined: February 26th, 2010, 3:12 am

Re: dbPicShow - proper usuage

1. You can use TTimer component.
2. Both of Execute and Stop methods test Busy property internally. So, there is no need to explicitly check this property.
3. Are you sure the images are not corrupted in the database? This may happen if images are in a string or memo field. To prevent this problem, either store images in a blob field or set Transliterate property of the string/memo field to False.
Kambiz

Kambiz

Posts: 2430
Joined: March 7th, 2003, 7:10 pm

Re: dbPicShow - proper usuage

1. Done.
2. Just curious as to why you asked me to check busy in the first post?
3. The fields are 'image' fields (mssql express). I import them as blobs. It doesn't happen to ALL the records and NOT the same ones. It's random as if the timer doesn't get the opportunity to complete, not sure. Keep in mind that I have THREE timers running. 7 of the dbPicshow on one, and the two other on separate timers. So I basically have 3 TTIMERS and 3 MultiMediaTimers. Could this be the problem?
kidjake28
Active Member

Posts: 11
Joined: February 26th, 2010, 3:12 am

Re: dbPicShow - proper usuage

Regarding Busy property, that time DBPicShow was in asynchronous mode. In manual or non-threaded modes when we call Stop method, the transition is really stopped when the function returns. But in the threaded mode, the transition may stop later and in a non-predictive time.

Probably the images are corrupted in the database. Save one of those images from database to a file to see whether the image is corrupted or the problem is because of something else.

I don't know how you are using the MultimediaTimers, but it may be the reason of the problem. When accessing shared objects/variables inside a multimedia timer, you have to synchronous your thread with other threads (including main VCL thread) that access the same object/variable.
Kambiz

Kambiz

Posts: 2430
Joined: March 7th, 2003, 7:10 pm

Re: dbPicShow - proper usuage

Again thanks very much for the replies.

I understand the busy property now. I had forgotten that we switched the dbPicshow's to manual mode.

I exported the images as you said and their fine. I'm pretty sure your right about the timers and not synchronizing. You see I'm an old school DOS Basic tinkerer. Having to wrap my head around threading is new for me. Can you summarize what I should/should not be doing? I realize you may not have the time or patients but if you could point me to an article I would great appreciate it.

This is my set up

1st timer interval 5 seconds (stops 7 dbPicshows advances the records and enables the 1st MultimediaTimer which disables progress<100)
2nd timer interval 15 seconds (stops 1 dbPicShow advances the record and enables the 2nd MultmediaTimer which disables after progress<100)
3rd timer interval 5 minutes (stops 1 dbPicShow advances the record and enabled the 3rd MultimediaTimer which disables after progress<100)

I'm pretty sure that there is no synchronizing going on simply for the fact that I don't know how to do it or what is needed to synchronize.

I just noticed that the Jedi Timer is a threaded timer and one of the properties is syncEvent (I've searched high and low for jedi documentation but can't find anything). Will this help me?
kidjake28
Active Member

Posts: 11
Joined: February 26th, 2010, 3:12 am

Re: dbPicShow - proper usuage

Here it is: Multithreading - The Delphi Way.

I am sure you will enjoy reading it.
Kambiz

Kambiz

Posts: 2430
Joined: March 7th, 2003, 7:10 pm

Re: dbPicShow - proper usuage

Not sure if your being sarcastic but "I will enjoy reading it".

Thanks so much for everything. I'll let you know how I make out.
kidjake28
Active Member

Posts: 11
Joined: February 26th, 2010, 3:12 am

I was serious.
Kambiz

Kambiz