从单独的线程访问TMediaPlayer.Position

时间:2011-11-29 01:02:07

标签: delphi

有没有理由为什么单独的线程无法查询TMediaPlayer对象的Position属性?

我编写了一个Delphi DLL,它是一个带有TMediaPlayer组件的表单。应用程序定期调用DLL,这些DLL调用可以在DLL的表单上查询TMediaPlayer对象的Position和Length值:

procedure TDLLForm.SongPosUpdate();
var
  new_pos: integer;
  new_len: integer;
begin
  new_pos := AudioPlayer.Position;
  new_len := AudioPlayer.Length;
end;

在加载DLL的应用程序的上下文中调用时,上述函数可以正常工作。但是,如果DLL创建一个单独的线程(子类化TThread)并且新线程调用相同的函数,则它会获得对象的Position和Length属性的无效值:

// TTimerThread: Constructor
constructor TTimerThread.Create(F: TDLLForm);
begin
  DllForm := F;
  inherited Create(True);
  inherited priority := tpHighest;
end;


// TTimerThread: Execute
procedure TTimerThread.Execute;
begin
  while not Terminated do
  begin
    DLLForm.SongPosUpdate();
    Sleep (1000);
  end;
end;

可以从线程成功查询TMediaPlayer对象的其他属性(例如AudioPlayer.FileName),但不能查找位置/长度。在开始播放的原始线程的上下文中没有调用TMediaPlayer会拒绝显示正确的位置/长度有什么原因吗?

1 个答案:

答案 0 :(得分:4)

直接从主VCL线程外部访问UI控件是不安全的。如果从工作线程查询,则无法保证任何属性都能正常工作。在这种情况下,FileName属性只读取属于TMediaPlayer类成员的String变量,因此通常足够安全,但PositionLength属性必须将MCI命令发送到媒体设备,这就是可能出现线程问题的地方。