Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1021
  • Last Modified:

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;
0
byungho
Asked:
byungho
  • 2
1 Solution
 
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
 
Computer101Commented:
Forced accept.

Computer101
EE Admin
0

Featured Post

Become an Android App Developer

Ready to kick start your career in 2018? Learn how to build an Android app in January’s Course of the Month and open the door to new opportunities.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now