Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 线程化以提高性能_Multithreading_Delphi - Fatal编程技术网

Multithreading 线程化以提高性能

Multithreading 线程化以提高性能,multithreading,delphi,Multithreading,Delphi,我从未使用过线程——从未想过我的代码会受益。但是,我认为线程可能会提高以下伪代码的性能: Loop through table of records containing security symbol field and a quote field Load a web page (containing a security quote for a symbol) into a string variable Parse the string for the quote

我从未使用过线程——从未想过我的代码会受益。但是,我认为线程可能会提高以下伪代码的性能:

Loop through table of records containing security symbol field and a quote field
    Load a web page (containing a security quote for a symbol) into a string variable
    Parse the string for the quote
    Save the quote in the table
    Get next record
end loop

加载每个网页花费的时间最多。对报价的解析相当快。我想我可以把一半的记录放在一个线程中,另一半放在第二个线程中。

如果记录的数量相对较少,比如说50个或更少,你可以为每个记录启动一个单独的线程,让它们并行运行,例如:

begin thread
  Load a web page for symbol into a string variable
  Parse the string for the quote
  Save the quote in the table
end thread

如果要处理的记录数较多,请考虑使用一组线程,这样就可以处理较小批次的记录,例如:

Create X threads
Put threads in a list

Loop through table of records
  Wait until a thread in pool is idle
  Get idle thread from pool
  Assign current security symbol to thread
  Signal thread
  Get next record
end loop

Wait for all threads to be idle
Terminate threads

有许多不同的方法可以实现上述功能,这就是我将其保留在伪代码中的原因。查看VCL的
TThread
TList
TEvent
类,或Win32 API
QueueUserWorkerItem()
函数,或者任何数量的第三方线程库。

在中,使用多级管道解决此问题非常简单-第一阶段在多个任务上运行并下载网页,第二阶段在一个实例中运行并将数据存储到数据库中。不久前,我写了一篇文档记录了这个解决方案

这个解决方案可以用以下代码总结(您必须填写HttpGet和Inserter方法中的一些地方)


使用线程框架,您可以在大量StackOverflow问题(进行搜索)中找到该框架的参考。检查:我会使用omnithreadlibrary,它非常高效,顺便说一句。看看omnixml,这些库也非常有用!在这种情况下,使用管道显然是有意义的。你需要更多的线程来下载,而不是通过声音来解析。谢谢你的评论。在跟进您的评论之后,我会喜欢做一些实验。我认为基于管道的解决方案在这里更合适,因为任务的组成部分在本质上是完全不同的。下载是IO绑定的,解析文件是CPU绑定的。@David:我需要做一些关于“管道”的研究,因为我从来没有听说过它。良好的网址链接将不胜感激。
Create X threads
Put threads in a list

Loop through table of records
  Wait until a thread in pool is idle
  Get idle thread from pool
  Assign current security symbol to thread
  Signal thread
  Get next record
end loop

Wait for all threads to be idle
Terminate threads
begin thread
  Loop until terminated
    Mark idle
    Wait for signal
    If not Terminated
      Load a web page for current symbol into a string variable
      Parse the string for the quote
      Save the quote in the table
    end if
  end loop
end thread
uses
  OtlCommon,
  OtlCollections,
  OtlParallel;

function HttpGet(url: string; var page: string): boolean;
begin
  // retrieve page contents from the url; return False if page is not accessible
end;

procedure Retriever(const input: TOmniValue; var output: TOmniValue);
var
  pageContents: string;
begin
  if HttpGet(input.AsString, pageContents) then
    output := TPage.Create(input.AsString, pageContents);
end;

procedure Inserter(const input, output: IOmniBlockingCollection);
var
  page   : TOmniValue;
  pageObj: TPage;
begin
  // connect to database
  for page in input do begin
    pageObj := TPage(page.AsObject);
    // insert pageObj into database
    FreeAndNil(pageObj);
  end;
  // close database connection
end;

procedure ParallelWebRetriever;
var
  pipeline: IOmniPipeline;
  s       : string;
  urlList : TStringList;
begin
  // set up pipeline
  pipeline := Parallel.Pipeline
    .Stage(Retriever).NumTasks(Environment.Process.Affinity.Count * 2)
    .Stage(Inserter)
    .Run;
  // insert URLs to be retrieved
  for s in urlList do
    pipeline.Input.Add(s);
  pipeline.Input.CompleteAdding;
  // wait for pipeline to complete
  pipeline.WaitFor(INFINITE);
end;