我使用此函数从DelphiDabbler获取delphi中的dos输出。但是如果该过程需要很长时间(例如:gammu getussd命令),则会导致我的应用程序暂时没有响应。
怎么避免这个?
function GetDosOutput(CommandLine: string; Work: string = 'C:\'): string;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
WasOK: Boolean;
Buffer: array[0..255] of AnsiChar;
BytesRead: Cardinal;
WorkDir: string;
Handle: Boolean;
begin
Result := '';
with SA do begin
nLength := SizeOf(SA);
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
try
with SI do
begin
FillChar(SI, SizeOf(SI), 0);
cb := SizeOf(SI);
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
wShowWindow := SW_HIDE;
hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
hStdOutput := StdOutPipeWrite;
hStdError := StdOutPipeWrite;
end;
WorkDir := Work;
Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine),
nil, nil, True, 0, nil,
PChar(WorkDir), SI, PI);
CloseHandle(StdOutPipeWrite);
if Handle then
try
repeat
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
if BytesRead > 0 then
begin
Buffer[BytesRead] := #0;
Result := Result + Buffer;
end;
until not WasOK or (BytesRead = 0);
WaitForSingleObject(PI.hProcess, INFINITE);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;
finally
CloseHandle(StdOutPipeRead);
end;
end;
作者:Joe Donth
答案 0 :(得分:4)
您可以使用一个简单的线程,并在OnTerminate事件中获取结果,该事件将在主线程的上下文中运行,因此不需要进一步的同步:
Type
TMyThread = Class(TThread)
private
FCmd: String;
FResult: String;
protected
Procedure Execute; override;
public
Constructor Create(const cmd: String;Notity:TNotifyEvent);
Property Result: String Read FResult;
End;
{ TMyTHread }
constructor TMyThread.Create(const cmd: String;Notity:TNotifyEvent);
begin
inherited Create(false);
FCmd := cmd;
FreeOnTerminate := True;
OnTerminate := Notity;
end;
procedure TMyThread.Execute;
begin
inherited;
FResult := GetDosOutput(FCmd);
end;
procedure TForm3.ThreadTerminated(Sender: TObject);
begin
Memo1.Lines.Text := TMyThread(Sender).Result;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
TMyThread.Create('DIR',ThreadTerminated);
end;