我正在从这些问题中学习这两个例子
我用什么技术来调试?
阅读代码并推测它将如何失败。
编译代码并让它运行,看看我是否正确。
这让我在第二个答案中找到了一个错误。这是我的评论:
您显示的示例有一个错误:如果您让任务完成它 将在标签上显示任务终止,而不是因为您完成任务 在设置标签的标题后调用
btnCancelTaskClick(Self);
完成任务会破坏将唤醒的线程 取消事件并打破循环导致发布第二个 消息将更改标题到任务终止。解决方案 将是在调用之前添加此行if not readyFlag then
第二个postmessage
。我建议编辑我希望你不介意
我现在使用的是什么技术?
现在,事情开始显现出丑陋的一面。我开始明白线程以非同步的方式运行(首先运行的线程将保持为???)。这些是我从第一个答案得到的结果。
重现的示例
创建一个新的VCL项目并在主窗体上添加两个TButtons。第一个按钮创建线程,第二个按钮释放它。
procedure TForm6.Button1Click(Sender: TObject);
begin
th.Free;
end;
procedure TForm6.Button2Click(Sender: TObject);
begin
th := TMyThread.Create;
end;
按下Button2,然后按下Button1,看看你能得到什么
结果(在调试器下):
在第一次运行中,我得到GetLastError = 6 = ERROR_INVALID_HANDLE。
奇怪的是,当主线程(主线程是执行销毁代码的线程)中的TEvent在析构函数中被销毁时,TEvent.WaitForMultiple
的结果不是wrAbandoned
。
在第二轮比赛中,我什么也没得到,线程被正确终止。
TEvent.WaitForMultiple
返回wrAbandoned
并且它一直在内部循环,直到终止为True。在没有调试器的情况下启动第二个答案时,10次运行都没有发生任何事情。
结论:我承认调试多线程应用程序是一场噩梦。我可以设计一个没有错误类的正确非死锁的最好方法也是一场噩梦。
从现在开始检查终止将是我的模式。
我从调试器中获得的错误总是在我从其中启动代码时出现(不知道为什么?我检查了异常是否被其他地方吞没但没有成功)。
问题如何在Delphi多线程代码中改进调试过程?所以我得到了更多这些错误。