Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
457 views
in Technique[技术] by (71.8m points)

delphi - About deadlock with TThread.synchronize

I use a library (WebRTC), that fire all event in one of its own and opaque background thread. So this is the flow I m facing :

:: MainUIThread
fMyWeRTC.doSomeThink;

:: WebRTC own and opaque background Thread
Procedure fMyWebRTC.renderFrame(frame: TRTCFrame);
begin
  TThread.synchronize(nil,
  procedure 
  begin
    ... Draw the frame .... // I can render only in main UI thread
  end;
end;

The problem is that when you call fMyWeRTC.doSomeThink;, the library internally call renderFrame in it's own background thread and wait its return (crazy but it's made like this, I can't change it). So here I enter in a deadlock :(

What are my option ?

  1. Use queue instead of synchronize? no possible because frame is alive only for the time of renderFrame. I don't also want to spend extra memory and time to duplicate it in memory.
  2. Do fMyWeRTC.doSomeThink in a background thread (with for example TAnonymousThread.execute)? that is quite opaque too, the doc doesn't say if we can call any functions from a background thread (when I tried, I have sometimes some exception). To stay on the safe way I prefer to call everything from the main UI thread

So how you can handle this situation?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One simple way to get around the deadlock is to avoid Synchronize altogether. We can't know why you are deadlocking from the code you've shown, but an option might be to use Queue with your own synchronization, ie:

Procedure fMyWebRTC.renderFrame(frame: TRTCFrame);
const
  RENDER_TIMEOUT = 1500;  { ms }
var
  LEvent : TEvent;
begin
  LEvent := TEvent.Create;      
  try
    LEvent.ResetEvent;
    TThread.Queue(nil,
      procedure 
      begin
        try
          // Draw Frame
        finally
          LEvent.SetEvent;
        end;
      end);
    LEvent.WaitFor(RENDER_TIMEOUT);
    { can check return value here and branch on failed wait, etc... 
      Be careful that LEvent may be freed below on a failed wait
      before it is used in the queued work above.  Need to handle
      that case yourself.
    }
  finally
    LEvent.Free;
  end;
end;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...