这是Android下的TThread的错误吗?

lok*_*oki 4 delphi android firemonkey

在Windows上,我们可以在同一个线程上调用几次MyThread.waitfor.如果线程已经终止没有问题,这将不会引发任何异常并立即返回(正常行为).

在Android上,它是不同的,如果我们调用两次MyThread.waitfor然后我们将在第二次尝试时使用"No such process".

function TThread.WaitFor: LongWord;
{$ELSEIF Defined(POSIX)}
var
  X: Pointer;
  ID: pthread_t;
begin
  if FExternalThread then
    raise EThread.CreateRes(@SThreadExternalWait);
  ID := pthread_t(FThreadID);
  if CurrentThread.ThreadID = MainThreadID then
    while not FFinished do
      CheckSynchronize(1000);
  FThreadID := 0;
  X := @Result;
  CheckThreadError(pthread_join(ID, X));
end;
{$ENDIF POSIX}
Run Code Online (Sandbox Code Playgroud)

发生错误是因为在调用waitfor时他们设置FThreadID:= 0所以当然任何进一步的调用都会失败

我认为必须写成:

function TThread.WaitFor: LongWord;
{$ELSEIF Defined(POSIX)}
begin
  if FThreadID = 0 then exit;
  ...
end;
{$ENDIF POSIX}
Run Code Online (Sandbox Code Playgroud)

你怎么看 ?我需要在emb中打开错误请求吗?

Dav*_*nan 5

文档pthread_join说:

加入先前已加入的线程会导致未定义的行为.

这解释了为什么TThread采取措施来避免调用未定义的行为.

设计中是否存在缺陷?这是值得商榷的.如果我们要考虑这门课程的设计,那就像设计师必须拓宽讨论范围一样.Windows线程可以由多个不同的线程等待.pthreads的情况并非如此.链接文档还说:

如果多个线程同时尝试使用同一个线程进行连接,则结果是未定义的.

所以我不认为Embarcadero可以合理地在Posix平台上实现与Windows上已有的相同的行为.可以肯定的是,正如您所描述的那样,他们可以从同一个线程重复等待特殊情况.好吧,他们必须坚持线程返回值,以便WaitFor可以返回它.但那只会让你在那里分道扬and,反正也不会有用.毕竟,为什么你会再次从同一个线程中等待?

我怀疑将FThreadID其设置为0以避免未定义的行为并以更强大的方式失败.但是,如果多个线程调用WaitFor则存在数据争用,因此仍然可以进行未定义的行为.

如果我们想要慈善事业,那么我们就可以

将这些具体细节留在一边,很明显,如果WaitFor通过调用实现,pthread_join那么跨平台的不同行为是不可避免的.Embarcadero试图调整TThread每个平台的实现,但由于平台功能不同,它们不能完全等效.Windows提供了比pthread更丰富的线程原语集.

如果Embarcadero选择了不同的路径,他们可以完美地对齐平台,但需要在Posix上更加努力.可以在那里复制Windows行为,但是这个特定的方法必须用其他东西来实现pthread_join.

面对现实,我认为你必须适应pthreads的不同功能.在pthreads中,仅仅为了方便起见,包括在线程上等待的能力.如果你真的想支持重复等待,你最好等待事件或条件变量.另一方面,您可能只需重新创建代码以确保只等待一次.

因此,总而言之,如果没有Embarcadero,你应该提出一个问题.他们可能会考虑支持您的方案.并且它值得在系统中出现问题.但是,如果他们选择不做任何事情并且因为更广泛的平台差异无法克服,以及课堂上需要额外的复杂性来支持你的无意义用例,那就不要感到惊讶.我希望我们可以同意的一件事是Delphi文档TThread.WaitFor应该涵盖这些问题.