如何设计“输送机”的操作与OmniThreadLibrary? [英] How do I design a "conveyor" of operations with OmniThreadLibrary?
问题描述
我有一个Windows Delphi应用程序,通过通知图标可以访问开始和停止菜单项。点击开始后,我需要执行以下操作(正如我看到的实现):
I have a Windows Delphi application with "Start" and "Stop" menu items accessible via a notification icon. After click on "Start", I need to do the following (as I see implementation):
-
ThreadMonitor :第一个线程正在等待指定文件夹中的指定文件的出现。
ThreadMonitor: The first thread is waiting for the appearance of the specified file in the specified folder.
ThreadParse :一次文件出现,它应该被转移到另一个线程(用于解析内容)并继续监视下一个文件。
ThreadParse: Once the file appears, it should be transferred to another thread (for parsing content) and continue monitoring for the next file.
ThreadDB :解析所有数据后,将其保存到MySQL数据库。 (另一个具有活动DB连接的后台线程)
ThreadDB: Once all data are parsed, save them into MySQL DB. (Another background thread with active DB connection?)
ThreadLog :如果步骤1-3中有任何错误,请写他们到一个日志文件(另一个后台线程?)而不中断步骤1-3。
ThreadLog: If there are any errors in the steps 1–3, write them to a log file (another background thread?) without interrupting the steps 1–3.
那就是它事实证明,像连续输送机一样,只有按停止才能停止工作。
从OmniThreadLibrary的各种方法中我应该使用什么?
That is, it turns out that something like a continuous conveyor, whose work is stopped only by pressing Stop. What should I use from a whole variety of methods of OmniThreadLibrary?
推荐答案
可能最好使用<一个href =http://otl.17slon.com/book/doku.php?id=book:highlevel:backgroundworker =nofollow> Parallel.BackgroundWorker 进行日志记录和 Parallel.Pipeline 用于数据处理。这是一个解决方案的草图(编译,但没有完全实现):
It would probably be best to use Parallel.BackgroundWorker for logging and Parallel.Pipeline for data processing. Here's a sketch of a solution (compiles, but is not fully implemented):
unit PipelineDemo1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
OtlCommon, OtlCollections, OtlParallel;
type
TfrmPipelineDemo = class(TForm)
btnStart: TButton;
btnStop: TButton;
procedure btnStartClick(Sender: TObject);
procedure btnStopClick(Sender: TObject);
private
FLogger : IOmniBackgroundWorker;
FPipeline: IOmniPipeline;
strict protected //asynchronous workers
procedure Asy_LogMessage(const workItem: IOmniWorkItem);
procedure Asy_Monitor(const input, output: IOmniBlockingCollection);
procedure Asy_Parser(const input: TOmniValue; var output: TOmniValue);
procedure Asy_SQL(const input, output: IOmniBlockingCollection);
public
end;
var
frmPipelineDemo: TfrmPipelineDemo;
implementation
uses
OtlTask;
{$R *.dfm}
procedure TfrmPipelineDemo.Asy_LogMessage(const workItem: IOmniWorkItem);
begin
//log workItem.Data
end;
procedure TfrmPipelineDemo.Asy_Monitor(const input, output: IOmniBlockingCollection);
begin
while not input.IsCompleted do begin
if FileExists('0.0') then
output.TryAdd('0.0');
Sleep(1000);
end;
end;
procedure TfrmPipelineDemo.Asy_Parser(const input: TOmniValue; var output: TOmniValue);
begin
// output := ParseFile(input)
FLogger.Schedule(FLogger.CreateWorkItem('File processed: ' + input.AsString));
end;
procedure TfrmPipelineDemo.Asy_SQL(const input, output: IOmniBlockingCollection);
var
value: TOmniValue;
begin
//initialize DB connection
for value in input do begin
//store value into database
end;
//close DB connection
end;
procedure TfrmPipelineDemo.btnStartClick(Sender: TObject);
begin
FLogger := Parallel.BackgroundWorker.NumTasks(1).Execute(Asy_LogMessage);
FPipeline := Parallel.Pipeline
.Stage(Asy_Monitor)
.Stage(Asy_Parser)
.Stage(Asy_SQL)
.Run;
end;
procedure TfrmPipelineDemo.btnStopClick(Sender: TObject);
begin
FPipeline.Input.CompleteAdding;
FPipeline := nil;
FLogger.Terminate(INFINITE);
FLogger := nil;
end;
end.
这篇关于如何设计“输送机”的操作与OmniThreadLibrary?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!