gpt4 book ai didi

multithreading - 如何在不卡住的情况下读取 blobfield?

转载 作者:行者123 更新时间:2023-12-03 15:58:11 26 4
gpt4 key购买 nike

我想从客户端(通过网络)读取 blobfield(带有 blobstream),但应用程序在获取数据时卡住。如何在不卡住并用进度条显示百分比的情况下读取 blobfield。 (我使用的是 Delphi 和 Firebird)

我正在使用独特的组件。我从以下位置找到了此代码:http://forums.devart.com/viewtopic.php?t=14629

但它无法正常工作:

const
BlockSize= $F000;
var
Blob: TBlob;
Buffer: array of byte;
p: pointer;
pos, count: integer;

UniQuery1.SQL.Text:= 'select * from TABLE1 where FIELD_ID = 1';
UniQuery1.Open;

blob:= uniquery1.GetBlob('DATA');
SetLength(buffer, blob.Size);
ProgressBar1.Position:= 0;
Application.ProcessMessages;

repeat
count:= Blob.Read(pos, blocksize, p);
ProgressBar1.Position:= Round(pos/Blob.Size * 100);
pos:= pos + count;
p:= pointer(integer(p) + count);
Application.ProcessMessages;
until count < blocksize;

PS:我已经设置了 uniquery 的选项:

cacheblobs:= false;
streamedblobls:= true;
deferredblobread:= true;

在repeat-until循环的第一步中,Blob.Read方法读取了所有流,因此无法正常工作。

最佳答案

您应该使用线程,这是 Delphi TThread 的示例:

type
TMyForm = class(TForm)
private
FPosition: Integer;
procedure ProgressUpdate;
procedure Execute;
end;

procedure TMyForm.ProgressUpdate;
begin
ProgressBar1.Position := FPosition;
end;

procedure TMyForm.Execute;
begin
FPosition:= 0;
ProgressUpdate;
Thread := TThread.CreateAnonymousThread(procedure
begin
repeat
// Do some long running stuff (in chunks, so we can update the position)
FPosition := CalculatePosition;
// Important: Synchronize will run ProgressUpdate in the main thread!
TThread.Synchronize(nil, ProgressUpdate);
until SomeCondition;
end
);
Thread.Start;
end;

因此,将此模式应用于您的代码后,我们得到:

type
TMyForm = class(TForm)
private
FPosition: Integer;
procedure ProgressUpdate;
procedure Execute;
end;

procedure TMyForm.ProgressUpdate;
begin
ProgressBar1.Position := FPosition;
end;

procedure TMyForm.Execute;
var
Blob: TBlob;
Thread: TThread;
begin
UniQuery1.SQL.Text := 'SELECT * FROM TABLE1 WHERE FIELD_ID = 1';
UniQuery1.Open;
Blob := UniQuery1.GetBlob('DATA');

FPosition:= 0;
ProgressUpdate;
Thread := TThread.CreateAnonymousThread(
procedure
const
BlockSize = $F000;
var
Buffer: array of Byte;
P: Pointer;
Pos, Count: Integer;
begin
SetLength(Buffer, Blob.Size);
repeat
Count := Blob.Read(Pos, BlockSize, P);
FPosition := Round(Pos / Blob.Size * 100);
Pos := Pos + Count;
P := Pointer(Integer(P) + Count);
// Important: Synchronize will run ProgressUpdate in the main thread!
TThread.Synchronize(nil, ProgressUpdate);
until Count < BlockSize;
end
);
Thread.Start;
end;

我删除了 Application.ProcessMessage 并将所有处理移至线程。

线程正在设置 FPosition 私有(private)属性,并使用 TThread.Synchronize 将 ProgressBar 位置设置为主线程中的 FPosition

如果您的 block 大小不够大,这可能仍会阻塞 UI(由于过度同步),因此请选择适当的 block 大小或添加一些更新延迟。

您必须确保匿名线程运行时主线程中不使用 UniQuery1 对象的连接,或者将连接和查询也移至该线程。

这也可能存在重入问题,但它应该让您了解如何使用线程进行后台处理。

PS:在线程中运行查询可能也是一个好主意,特别是如果它可能需要一些时间。

关于multithreading - 如何在不卡住的情况下读取 blobfield?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21180829/

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