我正在创建一个Delphi应用程序来从Internet下载文件,如果服务器支持范围请求它将是多线程的.进度也被转发回GUI.
当前的软件模型使用TThread组件.GUI调用a TDownloadThread然后生成TDownloadPartThreads- 这些是实际通过'WinHttp'进行下载的线程.
我的问题:CPU已用完,即使只下载4个线程的下载.
我的假设原因:
Synchronize(MainForm.UpdateProgress(Downloaded, TotalSize))我听到的AWFUL来完成的,也许我应该在线程之间共享一个对象,这样我可以使用主窗体上的计时器来访问它,以更新进度?我的解决方案
交错文件写入只写每个x字节.
更新TThread要使用的组件,OmniThreadLibrary并以某种方式将数据发送回主表单.TDownloadPart然后,每个线程将成为一个IOmniWorker并通过与主表单共享对象来发回其进度.然后,主窗体将使用计时器来更新其进度,如:ProgressBar1.Position := sharedDataObject.Progress;
希望有人可以指出我正确的方向!
我使用Omnithreadlibrary从一个线程中调用一个服务器方法,数据成功返回,但我使用返回的数据有麻烦,我尝试的一切都与AccessViolation或应用程序崩溃,尝试也设置数据集在一个链接到ClientDataSet的DataSetProvider,但是这里它也不起作用,最后我设置服务器方法返回OleVariant并将其直接设置为ClientDataSet的Data属性,但我也有错误.
我的目的是让请求在一个线程中完成,并将数据返回到主线程中的函数来填充网格.
有什么建议?
我试图用Delphi将+100文件上传到azure.但是,调用会阻塞主线程,因此我想通过异步调用或后台线程来执行此操作.
这就是我现在所做的事情(如此处所述):
procedure TCloudManager.UploadTask(const input: TOmniValue;
var output: TOmniValue);
var
FileTask:TFileTask;
begin
FileTask := input.AsRecord<TFileTask>;
Upload(FileTask.BaseFolder, FileTask.LocalFile, FileTask.CloudFile);
end;
function TCloudManager.MassiveUpload(const BaseFolder: String;
Files: TDictionary<String, String>): TStringList;
var
pipeline: IOmniPipeline;
FileInfo : TPair<String,String>;
FileTask:TFileTask;
begin
// set up pipeline
pipeline := Parallel.Pipeline
.Stage(UploadTask)
.NumTasks(Environment.Process.Affinity.Count * 2)
.Run;
// insert URLs to be retrieved
for FileInfo in Files do
begin
FileTask.LocalFile := FileInfo.Key;
FileTask.CloudFile := FileInfo.Value;
FileTask.BaseFolder := BaseFolder;
pipeline.Input.Add(TOmniValue.FromRecord(FileTask));
end;//for
pipeline.Input.CompleteAdding;
// wait for pipeline to complete
pipeline.WaitFor(INFINITE); …Run Code Online (Sandbox Code Playgroud) 我习惯于创建TThread后代来进行长时间的数据库操作.我通常的构造看起来像这样:
interface
type
TMyDBOp = class(TThread)
private
FConnection: TADOConnection;
FCommand1: TADOCommand;
FCommand2: TADOCommand; // and many more privated objects, vars ...
procedure InitDB;
procedure DoneDB;
procedure DoDBStuff; // and many more procedures and functions to structure the code
protected
procedure Execute; override;
public
constructor Create; reintroduce;
property X: T... // and many more properties to set on thread creation
end;
implementation
constructor TMyDBOp.Create;
begin
inherited Create(False);
end;
procedure TMyDBOp.InitDB;
begin
FConnection:= TADOConnection.Create(nil);
// setup all connection props, setup all other …Run Code Online (Sandbox Code Playgroud) 我正在使用Delphi 2010开发一个多线程客户端应用程序(使用优秀的OmniThreadLibrary),因为我经常从一个线程交换到另一个线程,所以我很难进行调试.
我想知道是否有可能(使用任何工具或插件,我不在乎!)找到当前执行点,不仅是当前线程,还有所有其他线程.
一个简单的例子/报告:
Thread #1 stopped at line #5
Thread #2 stopped at line #25 (<-- breakpoint set here, causing Delphi to stop)
Thread #3 stopped at line #78
Run Code Online (Sandbox Code Playgroud)
我的目标是"看到"当Delphi在某个断点处停止时其他线程正在做什么,而不仅仅是使用日志(或者不那么有用的Thread 12345停止),而是检查它们就好像断点停在它们处.
我希望我的问题很清楚,请注意它已经过了午夜,所以如果我的问题听起来很愚蠢,请不要怪我!
是否有可能以某种方式监控管道任务?我试图像这样为每个任务添加监视器
FPipeline := Parallel.Pipeline()
.Stage(StageWorker1, Parallel.TaskConfig.MonitorWith(MyMonitor))
.NumTasks(MaxReadThreadCount)
.Stage(StageWorker2, Parallel.TaskConfig.MonitorWith(MyMonitor))
.Run();
Run Code Online (Sandbox Code Playgroud)
但获得异常"任务只能用一个监视器监视"(据我所知,这是因为已经为管道阶段安装了内部隐藏监视器).
我想知道我是否可以使用 OTL 来并行化这个循环。
我有以下代码。
for i := 1 to XRes do
begin
for j := 1 to XRes do
begin
GridMat.Elem[i,j] := StrToFloat(ListOfValues[(i-1)+((j-1)*Xres)]);
end;
Invalidate;
end;
Run Code Online (Sandbox Code Playgroud)
是否可以将 GridMat(来自 SDL_matrix.TMatrix)作为参数传递给所有并行 ForEach 并将值添加到它。
我在我的dll中使用OmniThreadLibrary 2.09,主应用程序和dll使用相同的SimpleShareMem内存管理器.
我用这段代码创建了自己的监视器:
FMonitor: TOmniEventMonitor;
...
FMonitor := TOmniEventMonitor.Create(nil);
Run Code Online (Sandbox Code Playgroud)
当我尝试使用此监视器创建新任务时,我收到错误"只能使用单个监视器监视任务"
FTask := OtlTaskControl.CreateTask(TaskWorker)
.OnMessage(
procedure(const ATaskControl: IOmniTaskControl; const AMsg: TOmniMessage)
begin
...
end)
.MonitorWith(FMonitor) // <----- Error
.OnTerminated(
procedure (const ATaskControl: IOmniTaskControl)
begin
...
end)
.Run();
Run Code Online (Sandbox Code Playgroud)
如何使用自己的显示器监控我的任务?
我在控制台应用程序中的BackgroundWorker(高级OmniThreadLibrary组件)中的主线程有问题.主线程(整个应用程序)中的对象在为后台任务调度WorkItems后立即死亡.主线程不等待OnRequestDone方法调用.
procedure TEntityIndexer.StartReindex;
begin
if LoadTable then
// in ProcessRecords method I schedule WorkItems for BackgroundWorker
ProcessRecords;
// when ProcessRecords method is done, application is at the end and
// main thread is destoryed, so object in main thread is destroyed
// and BackgroundWorker in object in main thread is destroyed too
end;
procedure TEntityIndexer.ProcessRecords;
var
_id: Integer;
_omniValue: TOmniValue;
begin
FVTable.First;
while not FVTable.Eof do
begin
_id := FVTable.FieldByName('record_id').AsInteger;
WriteLogText(cProcesIndexLog, 'ID=' + IntToStr(_id) + '....PROCESS STARTED');
_omniValue := TOmniValue.CreateNamed( …Run Code Online (Sandbox Code Playgroud) 创建一个VCL表单应用程序,在表单上放置一个TButton和一个TMemo,并在按钮的OnClick处理程序中编写此代码:
uses
OtlParallel, OtlTaskControl;
procedure TForm2.btnStartLoopClick(Sender: TObject);
var
starttime: Cardinal;
k: Integer;
begin
mmoTest.Lines.Clear;
for k := 1 to 50 do
mmoTest.Lines.Add('Line ' + IntToStr(k));
starttime := GetTickCount;
Parallel.Async(
procedure
var
i: Integer;
begin
for i := 1 to 50 do
begin
Sleep(100);
mmoTest.Lines[i - 1] := mmoTest.Lines[i - 1] + FormatDateTime(' nn:ss:zzz', Now);
end;
end,
Parallel.TaskConfig.SetPriority(TOTLThreadPriority.tpHighest).OnTerminated(
procedure
begin
mmoTest.Lines.Add(IntToStr(GetTickCount - starttime) + ' milliseconds');
end));
end;
Run Code Online (Sandbox Code Playgroud)
现在运行程序并进行此测试:
单击按钮,只需等待循环完成并查看备忘录最后一行中显示的时间:它应该是大约5300毫秒.
现在再次单击按钮,单击并按住表单的标题栏并快速移动表单,直到循环结束.现在再看一下备忘录的最后一行:在我的测试中,时间超过7000毫秒.显然,主线程是阻塞并行线程!
那么如何避免阻塞并行线程的主线程呢?
delphi ×10
delphi-xe4 ×2
azure ×1
dataset ×1
datasnap ×1
debugging ×1
delphi-xe2 ×1
dll ×1
winhttp ×1