有没有理由为什么单独的线程无法查询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会拒绝显示正确的位置/长度有什么原因吗?
答案 0 :(得分:4)
直接从主VCL线程外部访问UI控件是不安全的。如果从工作线程查询,则无法保证任何属性都能正常工作。在这种情况下,FileName
属性只读取属于TMediaPlayer
类成员的String变量,因此通常足够安全,但Position
和Length
属性必须将MCI命令发送到媒体设备,这就是可能出现线程问题的地方。