gpt4 book ai didi

multithreading - 尝试通过 tcp/ip 发送文件时表单卡住,Delphi 2010

转载 作者:行者123 更新时间:2023-12-03 15:56:19 25 4
gpt4 key购买 nike

我面临以下问题。我和我的一个 friend 使用超高频数据调制解调器建立了无线网络。当我尝试发送文件(例如照片)并且连接正常时没有问题。但是,当我尝试发送文件并且由于某种原因有一段时间没有连接时,表单会卡住,直到重新建立。有人可以帮我吗?这是我在服务器端和客户端使用的代码(Delphi 2010)。

客户端(传输文件[如果连接暂时或永久丢失,此表单将卡住]):

procedure TForm17.BtnSendFile(Sender: TObject);
var
FS: TFileStream;
filename: string;
begin
filetotx := 'temp.jpg';
FS := TFileStream.Create(filetotx, fmOpenRead, fmShareDenyWrite);
FS.Position := 0;
try
Form1.IdTCPClient1.Socket.LargeStream := true;
Form1.IdTCPClient1.Socket.WriteLn('PIC');
Form1.IdTCPClient1.Socket.Write(FS, 0, true);
finally
FS.Free;
end;
end;

服务器端(接收文件)

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
s, filename:string;
FS: TFileStream;
Jpg: TJpegImage;
begin
S := AContext.Connection.Socket.ReadLn;
if S = 'PIC' then
begin
filename := 'PIC_' + datetostr(date) + ' ' + timetostr(time) + '.jpg';
filename := StringReplace(filename, '/', '-', [rfReplaceAll]);
filename := StringReplace(filename, ':', '_', [rfReplaceAll]);
filename := extractfilepath(Application.exename) + 'PIC\' + filename;
FS := TFileStream.Create(filename, fmCreate);
FS.Position := 0;
AContext.Connection.Socket.LargeStream := true;
AContext.Connection.Socket.ReadStream(FS);
Jpg := TJpegImage.Create;
FS.Position := 0;
Jpg.LoadFromStream(FS);
form26.image1.Picture.Assign(Jpg);
try
Jpg.Free;
FS.Free;
finally
//send feedback file received
AContext.Connection.Socket.WriteLn('PICOK');
TIdNotify.NotifyMethod(form26.Show);
end;
end;

客户端(接收反馈“PICOK”)

type
TReadingThread = class(TThread)
protected
FConn: TIdTCPConnection;
procedure Execute; override;
procedure DoTerminate; override;
public
constructor Create(AConn: TIdTCPConnection); reintroduce;
end;

constructor TReadingThread.Create(AConn: TIdTCPConnection);
begin
TLog.AddMsg('Client Thread Created');
FConn := AConn;
inherited Create(False);
end;


procedure TReadingThread.Execute;
begin
while not Terminated do
begin
if S='MSGOK' then
.
.
else if S = 'PICOK' then
begin
Do Something
end
end;
end;

procedure TReadingThread.DoTerminate;
begin
TLog.AddMsg('Disconnected');
inherited;
end;

最佳答案

您的客户端代码正在主 UI 线程的上下文中发送文件。这就是 UI 卡住的原因 - 发送繁忙时没有消息正在处理。要么将该代码移动到工作线程中(首选),要么将 TIdAntiFreeze 组件拖放到您的表单上。

就实际文件传输而言,您的服务器代码没有问题,但是您的 try/finally block 是错误的,并且您直接访问 TImage 而不进行同步与主 UI 线程。您在调用 form26.Show 时已经进行了同步,只需在调用 form26.image1.Picture.Assign(Jpg) 时也进行同步即可。试试这个:

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
S, Filename: string;
FS: TFileStream;
Jpg: TJpegImage;
begin
S := AContext.Connection.Socket.ReadLn;
if S = 'PIC' then
begin
Filename := ExtractFilePath(Application.ExeName) + 'PIC\' + FormatDateTime('"PIC_"mm"-"dd"-"yyyy" "hh"_"nn"_"ss".jpg"', Now);
FS := TFileStream.Create(Filename, fmCreate);
try
AContext.Connection.Socket.LargeStream := true;
AContext.Connection.Socket.ReadStream(FS);
FS.Position := 0;
Jpg := TJpegImage.Create;
try
Jpg.LoadFromStream(FS);
TThread.Synchronize(nil,
procedure
begin
Form26.Image1.Picture.Assign(Jpg);
Form26.Show;
end;
);
finally
Jpg.Free;
end;
finally
FS.Free;
end;
//send feedback file received
AContext.Connection.Socket.WriteLn('PICOK');
end;
end;

或者这个:

type
TMyNotify = class(TIdNotify)
protected
procedure DoNotify; override;
public
Jpg: TJpegImage;
constructor Create;
destructor Destroy; override;
end;

constructor TMyNotify.Create(Stream: TStream);
begin
inherited;
Jpg := TJpegImage.Create;
Jpg.LoadFromStream(Stream);
end;

destructor TMyNotify.Destroy;
begin
Jpg.Free;
inherited;
end;

procedure TMyNotify.DoNotify;
begin
Form26.Image1.Picture.Assign(Jpg);
Form26.Show;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
S, Filename: string;
FS: TFileStream;
begin
S := AContext.Connection.Socket.ReadLn;
if S = 'PIC' then
begin
Filename := ExtractFilePath(Application.ExeName) + 'PIC\' + FormatDateTime('"PIC_"mm"-"dd"-"yyyy" "hh"_"nn"_"ss".jpg"', Now);
FS := TFileStream.Create(Filename, fmCreate);
try
AContext.Connection.Socket.LargeStream := true;
AContext.Connection.Socket.ReadStream(FS);
FS.Position := 0;
TMyNotify.Create(FS).Notify;
finally
FS.Free;
end;
//send feedback file received
AContext.Connection.Socket.WriteLn('PICOK');
end;
end;

关于multithreading - 尝试通过 tcp/ip 发送文件时表单卡住,Delphi 2010,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31067055/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com