Multithread update screen using directdraw -> DeadLock

My app transfer images from server and display images to form!!

It works fine in my desktop(XP SP2, Intel Core2 CPU 6400@ 2.13GHz, 2.14GHz, 2GB RAM, NVIDIA GeForce 7950 GT)

But specific notebook(HP, XP SP2, Intel Core2 CPU T7400@ 2.13GHz, 2.16GHz, 1GB RAM, ATI Mobility Radeon X1600) was hanging after running about 3~5 minutes!!

I found where is problem by logging!! The problem `DrawChannelText()` method!!

I assume the problem is multi-thread update to screen!!

But I can not sure it, I try to synchronize by TCanvas.Lock/UnLock method!!

1. Connection Thread -> Fire DrawImageCallback for every frame image -> DrawChannelText() to draw text
2. Main Thread -> WM_TIMER for update screen every 50ms

I can not TThread.Synchronize to synchronize update screen. Because thread-callback was fired in dll.

I use TDisplay and TSurface classes to use directdraw (DDUtil.pas, http://www.clootie.ru/delphi/download_dx92.html)

Following DrawImageCallback() method fired by separated thread for connection.

There are many connections to display remote server screen.


procedure TMainForm.DrawImageCallback(Channel: PChannel; AVideoData: TVideoData);
var
  DstR, SrcR: TRect;
  hr: HRESULT;
  ddsd: TDDSURFACEDESC2;
  pDDS: IDIRECTDRAWSURFACE7;
  pDst: Pointer; // memory image buffer
begin
  Canvas.Lock;
  try
    pDDS := FChannelSurface.GetDDrawSurface;

    FillChar(ddsd, SizeOf(ddsd), 0);
    ddsd.dwSize := SizeOf(ddsd);

    // Lock the surface to directly write to the surface memory
    hr := pDDS.Lock(nil, ddsd, DDLOCK_SURFACEMEMORYPTR or DDLOCK_WAIT, 0);
    if FAILED(hr) then
    begin
      if not RecreateSurfaces then Exit;
      hr := pDDS.Lock(nil, ddsd, DDLOCK_SURFACEMEMORYPTR or DDLOCK_WAIT, 0);
      if FAILED(hr) then Exit;
    end;

    pDst := ddsd.lpSurface;
    // Set 32bit Bitmap Data to DirectDraw7 Draw Buffer
    Move(Pointer(AVideoData.Param1)^, pDst^, AVideoData.Param2);

    pDDS.Unlock(nil);

    DstR := Channel.Rect;

    SrcR := Rect(0, 0, AVideoData.Width, AVideoData.Height);

    FDisplay.Blt(@DstR, FChannelSurface, @SrcR);

    Channel.Timestamp := AVideoData.Timestamp;
   
    DrawChannelText(Channel);

    NeedPaint := True; // Update mainform timer protected property by critical section

  finally
    Canvas.Unlock;
  end;
end;


procedure TMainForm.DrawChannelText(Channel: PChannel);
var
  L, T, W, H: Integer;
  R: TRect;
  HR: HRESULT;
  S, DateStr, TimeStr: string;
  DC: HDC;
  StrSize, DateSize, TimeSize: TSize;
  DstR: TRect;
begin
  L := Channel.Rect.Left;
  T := Channel.Rect.Top;
  W := Channel.Rect.Right - Channel.Rect.Left;
  H := Channel.Rect.Bottom - Channel.Rect.Top;

  Canvas.Lock;
  try
    if (nil = FTextSurface) or
       (FTextSurface.Width <> W) or
       (FTextSurface.Height <> H) then
    begin
      if nil <> FTextSurface then
        FreeAndNil(FTextSurface);

      HR := FDisplay.CreateSurface(FTextSurface, W, H);
      if DD_OK <> HR then Exit;
      FTextSurface.SetColorKey(0);
    end;
    FTextSurface.Clear(0);

    S := IntToStr(Channel.Channel + 1) + ' ' +Channel.ChannelName;
    FTextSurface.DrawText(Font.Handle, S, 3, 2, 0, ColorToRGB(FTextColor));

    HR := FTextSurface.GetDDrawSurface.GetDC(DC);
    if DD_OK <> HR then Exit;
    SelectObject(DC, SelFont.Handle);
    DateStr := DateToStr(DateOf(Channel.TimeStamp));
    GetTextExtentPoint32(DC, PChar(DateStr), Length(DateStr), DateSize);
    TimeStr := TimeToStr(TimeOf(Channel.Timestamp);
    GetTextExtentPoint32(DC, PChar(TimeStr), Length(TimeStr), TimeSize);
    FTextSurface.GetDDrawSurface.ReleaseDC(DC);

    FTextSurface.DrawText(SelFont.Handle, DateStr,
      W - DateSize.cx - 2, 2, 0, ColorToRGB(FTextColor));
    FTextSurface.DrawText(SelFont.Handle, TimeStr,
      W - TimeSize.cx - 2, DateSize.cy + 2, 0, ColorToRGB(FTextColor));
    end;

    HR := FTextSurface.GetDDrawSurface.GetDC(DC);
    if DD_OK <> HR then Exit;
    SelectObject(DC, SelFont.Handle);
    S := Channel.Session.Profile.Address;
    GetTextExtentPoint32(DC, PChar(S), Length(S), StrSize);
    FTextSurface.GetDDrawSurface.ReleaseDC(DC);
    FTextSurface.DrawText(SelFont.Handle, S, 2, H - StrSize.cy - 2, 0, ColorToRGB(FTextColor));

    FDisplay.Blt(L, T, FTextSurface, nil);
  finally
    Canvas.Unlock;
  end;
end;

// fired every 50ms
procedure TMainForm.WMTimer(var msg: TMessage);
begin
  if NeedPaint and (nil <> FDisplay) then
  begin
    FDisplay.Flip;
    NeedPaint := False;
  end;
end;
byunghoAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

2266180Commented:
you have some problems in your code. first of all, remember, that when you have a dedalock, the solution is not inserting another lock. the deadlock means that some locks went wrong.

so, to the problems. in your first procedure, you make some locks and then you exit the procedure in case of error without unlocking. which ... nedless to say it's wrong.

so replace all the exit, with abort calls. this will raise a silent exception and go through all finalize calls.
apply this logic to al your program.

also put the operations between pdds lock and unlock into a try finally. just in case ;)
again, if you have any other lock/unlock calls not protected by try/finally or try/except, then do it now.

that's what I am seeing for now. let me know if this fixes it or not.
0
byunghoAuthor Commented:
I  try to protect exit call with try ... finally ... end; Is it wrong?

I will be put pdds lock and unlock into try ... finally .. end!! thank you!



0
2266180Commented:
exit, wille xit the procedure and NOT execute the finally statements. that is why you need abort instead of exit.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Computer101Commented:
Forced accept.

Computer101
EE Admin
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.