在Delphi 10中,我有一个FormA
,它在iTask(线程)“Tarefaproc”中调用Oracle存储过程。此storedproc更新了一个表格,该表格将由另一个Tchart
中的FormB
使用。
我在FormB
Tarefaproc之后呼叫iTask
但是,它不起作用,它冻结了应用程序!!感谢您帮助我们理解并解决了这个问题。
请参阅我的代码:
procedure TFormA.SpeedButtonChamaGrafico(Sender: TObject);
var
Tarefaproc, Tarefagrafico : iTask;
begin
// Call StoredProc inside iTask ==> this WORKS PERFECTLY !!
Tarefaproc := TTask.Create( procedure ()
begin
with FDStoredProc1 do
begin
Prepare;
Params[0].Value := StrToInt(EditCenario.Text);
Execproc;
end;
end);
Tarefaproc.Start;
// Next, calls FormB inside another iTASK ==> DOESN'T WORK , it frozes the application !
Tarefagrafico := TTask.Create(
procedure ()
begin
try
Application.CreateForm(TformB,FormB);
FormB.ShowModal;
finally
Freeandnil(formB);
end;
end);
Tarefagrafico.Start;
end;
答案 0 :(得分:3)
无法从线程访问VCL。 相反,queue该方法调用模态表单以便稍后在主线程中执行。
procedure TFormA.SpeedButtonChamaGrafico(Sender: TObject);
var
value : Integer;
begin
value := StrToInt(EditCenario.Text); // Avoid vcl access from thread !!
TTask.Create(
procedure
begin
with FDStoredProc1 do
begin
Prepare;
Params[0].Value := value;
Execproc;
end;
// Next, queue method for later execution in main thread
TThread.Queue(nil,
procedure
var
FormB : TFormB; // Use local form variable
begin
FormB := TFormB.Create(nil); // Way to create form dynamically
try
// Here you can add data into FormB from the database extraction !!
// It is safe, since this call is executing in the main thread.
FormB.ShowModal;
finally
Freeandnil(FormB);
end;
end);
end).Start;
end;
请注意,即使从线程中读取vcl属性也是危险的。 此外,应避免使用全局表单变量。从IDE创建表单时,我要做的第一件事就是删除创建的全局表单变量。
来自TThread.Queue
的文档:
在主线程中执行方法调用。 队列导致AMethod指定的调用使用主线程异步执行,从而避免多线程冲突。