{"id":3492,"date":"2016-01-22T21:53:08","date_gmt":"2016-01-22T13:53:08","guid":{"rendered":"http:\/\/blog.qdac.cc\/?p=3492"},"modified":"2016-01-22T21:55:15","modified_gmt":"2016-01-22T13:55:15","slug":"qworker-%e5%88%b6%e4%bd%9c%e5%a4%9a%e7%ba%bf%e7%a8%8b%e6%97%a5%e5%bf%97%e8%be%93%e5%87%ba%e6%9f%a5%e7%9c%8bdemo","status":"publish","type":"post","link":"https:\/\/blog.qdac.cc\/?p=3492","title":{"rendered":"[QWorker] \u5236\u4f5c\u591a\u7ebf\u7a0b\u65e5\u5fd7\u8f93\u51fa\u67e5\u770bDemo"},"content":{"rendered":"<p>\u8981\u89e3\u51b3\u7684\u95ee\u9898\uff1a \u6709\u591a\u4e2a\u7ebf\u7a0b\u8f93\u51fa\u65e5\u5fd7\uff0c\u65e5\u5fd7\u5185\u5bb9\u9700\u8981\u5728\u5217\u8868\u6846\u4e2d\u663e\u793a\u51fa\u6765\uff0c\u4e0d\u7ba1\u65e5\u5fd7\u8f93\u51fa\u7684\u9891\u7387\u5feb\u6162\uff0c\u754c\u9762\u4e0d\u80fd\u5361\uff0c\u4e0d\u80fd\u95ea\u70c1\u3002\u8d85\u8fc710\u4e07\u884c\u65e5\u5fd7\u65f6\uff0c\u81ea\u52a8\u5220\u9664\u6700\u5f00\u59cb\u76841\u4e07\u884c\u65e5\u5fd7\u3002<\/p>\n<p>\u6b64\u95ee\u9898\u6d89\u53ca\u591a\u7ebf\u7a0b\u7f16\u7a0b\uff0c\u591a\u7ebf\u7a0b\u8f93\u51fa\u65f6\u8981\u66f4\u65b0\u754c\u9762\u7684\u663e\u793a\u3002<\/p>\n<p>\u591a\u7ebf\u7a0b\u7684\u4e1c\u897f\uff0c\u5f53\u7136\u4e0d\u80fd\u5fd8\u4e86QWorker\u8fd9\u6837\u7684\u795e\u5668\uff0c\u4e0b\u9762\u6211\u4eec\u5c31\u6765\u4f7f\u7528QWorker\u89e3\u51b3\u95ee\u9898\uff0c\u54e6\uff0c\u4e0d\u5bf9\uff0c\u662f\u7528YxdWorker\u6765\u89e3\u51b3\u95ee\u9898\uff08\u4e3a\u4ec0\u4e48\u662fYxdWorker\uff1f\u54c8\uff0c\u8fd9\u662f\u5b9d\u5b9d\u7684\u4fee\u6539\u7248\u672c\u5566\uff0c\u5c01\u88c5\u6210\u4e86\u81ea\u5df1\u559c\u6b22\u7684\u6837\u5b50\uff0c\u5176\u5b9e\u548cQWorker\u5dee\u4e0d\u591a\uff0c\u6709\u5174\u8da3\u53ef\u4ee5\u5230 SVN:\u00a0 <a href=\"https:\/\/github.com\/yangyxd\/YxdWorker\" target=\"_blank\">https:\/\/github.com\/yangyxd\/YxdWorker<\/a>\u4e0b\u8f7d\u3002\uff09<\/p>\n<p>\u4e00\u3001\u5148\u5728\u5728\u641c\u7d22\u8def\u5f84\u4e2d\u6dfb\u52a0\u5bf9YxdWorker\u7684\u5f15\u7528\uff0c\u7136\u540e\u5728\u7a97\u4f53\u4e0a\u653e\u4e00\u4e2aListView, Name=ListView1\uff0c\u518d\u653e\u4e00\u4e2aCheckBox, Name=CheckBox1\u3002\u6548\u679c\u5982\u4e0b\uff1a<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3494\" src=\"https:\/\/blog.qdac.cc\/wp-content\/uploads\/2016\/01\/QQ\u622a\u56fe20160122210453.png\" alt=\"QQ\u622a\u56fe20160122210453\" width=\"610\" height=\"552\" srcset=\"https:\/\/blog.qdac.cc\/wp-content\/uploads\/2016\/01\/QQ\u622a\u56fe20160122210453.png 610w, https:\/\/blog.qdac.cc\/wp-content\/uploads\/2016\/01\/QQ\u622a\u56fe20160122210453-300x271.png 300w\" sizes=\"auto, (max-width: 610px) 100vw, 610px\" \/><\/p>\n<p>ListView1\u7684OwnerData\u5c5e\u6027\u8bbe\u4e3aTrue\uff0cViewStyle\u5c5e\u6027\u8bbe\u4e3avsReport\uff0c\u6dfb\u52a0\u4e00\u5217\u201c\u65e5\u5fd7\u5185\u5bb9\u201d\u3002<\/p>\n<p>&nbsp;<\/p>\n<p>\u4e8c\u3001 \u5f00\u59cb\u5199\u4ee3\u7801<\/p>\n<pre class=\"lang:delphi decode:true\">unit Unit1;\r\n\r\ninterface\r\n\r\nuses\r\n  YxdWorker, SyncObjs, CommCtrl,\r\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\r\n  Dialogs, ComCtrls, StdCtrls;\r\n\r\ntype\r\n  TForm1 = class(TForm)\r\n    CheckBox1: TCheckBox;\r\n    ListView1: TListView;\r\n    Button1: TButton;\r\n    Button2: TButton;\r\n    Button3: TButton;\r\n    Button4: TButton;\r\n    procedure FormCreate(Sender: TObject);\r\n    procedure FormDestroy(Sender: TObject);\r\n    procedure ListView1Data(Sender: TObject; Item: TListItem);\r\n    procedure Button2Click(Sender: TObject);\r\n    procedure Button3Click(Sender: TObject);\r\n    procedure Button4Click(Sender: TObject);\r\n    procedure Button1Click(Sender: TObject);\r\n    procedure CheckBox1Click(Sender: TObject);\r\n  private\r\n    { Private declarations }\r\n    FLogs: TStrings;       \/\/ \u5b58\u653e\u65e5\u5fd7\u5185\u5bb9\r\n    FAutoScroll: Boolean;  \/\/ \u662f\u5426\u81ea\u52a8\u6eda\u52a8\r\n    FLogsIsDel: Boolean;   \/\/ \u662f\u5426\u5df2\u7ecf\u5220\u9664\u65e5\u5fd7\r\n    FLogRef: Integer;      \/\/ \u72b6\u6001\u8ba1\u6570\u5668\r\n    FLocker: TCriticalSection;\r\n\r\n    FTestRef: Integer;\r\n  public\r\n    { Public declarations }\r\n    procedure DoDataChange();\r\n    procedure DoWriteLog(Sender: TObject; const Log: string);\r\n    procedure OnDataChange(AJob: PJob);\r\n\r\n    procedure DoTest(AJob: PJob);\r\n    procedure Log(const Text: string);\r\n  end;\r\n\r\nvar\r\n  Form1: TForm1;\r\n\r\nimplementation\r\n\r\n{$R *.dfm}\r\n\r\n{ TForm1 }\r\n\r\nprocedure TForm1.Button1Click(Sender: TObject);\r\nbegin\r\n  Workers.Post(DoTest, nil);\r\nend;\r\n\r\nprocedure TForm1.Button2Click(Sender: TObject);\r\nbegin\r\n  FLocker.Enter;\r\n  FLogs.Clear;\r\n  FLogsIsDel := True;\r\n  FLocker.Leave;\r\n  DoDataChange();\r\nend;\r\n\r\nprocedure TForm1.Button3Click(Sender: TObject);\r\nbegin\r\n  Log('\u5199\u4e00\u884c\u65e5\u5fd7');\r\nend;\r\n\r\nprocedure TForm1.Button4Click(Sender: TObject);\r\nbegin\r\n  Workers.Clear(DoTest, nil);\r\nend;\r\n\r\nprocedure TForm1.CheckBox1Click(Sender: TObject);\r\nbegin\r\n  FLocker.Enter;\r\n  FAutoScroll := CheckBox1.Checked;\r\n  FLocker.Leave;\r\nend;\r\n\r\nprocedure TForm1.DoDataChange;\r\nbegin\r\n  \/\/ FLogRef \u5f88\u5173\u952e\uff0c\u51b3\u5b9a\u4ec0\u4e48\u65f6\u5019\u771f\u6b63\u66f4\u65b0\u663e\u793a\u3002\r\n  \/\/ \u591a\u7ebf\u7a0b\u5199\u65e5\u5fd7\u65f6\uff0cFLogRef &gt; 1\uff0c\u90a3\u4e48\u4e5f\u53ea\u66f4\u65b0\u4e00\u6b21\u3002\r\n  if InterlockedIncrement(FLogRef) = 1 then\r\n    \/\/ \u5ef6\u65f650ms\u66f4\u65b0\u3002\u6b64\u503c\u8bbe\u5b9a\u7684\u8d8a\u5927\uff0c\u5217\u8868\u66f4\u65b0\u7684\u8d8a\u6162\u3002\r\n    \/\/ \u4e0d\u5ef6\u65f6\u7684\u8bdd\uff0c\u754c\u9762\u5237\u65b0\u592a\u5feb\uff0c\u5360\u7528\u8d44\u6e90\u4f1a\u6bd4\u8f83\u5927\r\n    Workers.Post(OnDataChange, nil, True, 50)\r\n  else\r\n    InterlockedDecrement(FLogRef);\r\nend;\r\n\r\nprocedure TForm1.DoTest(AJob: PJob);\r\nvar\r\n  I, M: Integer;\r\nbegin\r\n  M := 0;\r\n  while (not AJob.IsTerminated) and (M &lt; 10000) do begin\r\n    Inc(M);\r\n    I := InterlockedIncrement(FTestRef);\r\n    Log(Format('\u65e5\u5fd7\u5185\u5bb9\u3002\u5de5\u4f5c\u8005\uff1a%d. (%d)', [AJob.Handle, I]));\r\n    Sleep(100);\r\n  end;\r\nend;\r\n\r\nprocedure TForm1.DoWriteLog(Sender: TObject; const Log: string);\r\nvar\r\n  I: Integer;\r\nbegin\r\n  if Assigned(FLogs) and (Assigned(Self)) then begin\r\n    FLocker.Enter;\r\n    \/\/ \u5927\u4e8e10\u4e07\u884c\u65f6\uff0c\u5220\u9664\u524d\u9762\u76841\u4e07\u884c\r\n    if FLogs.Count &gt; 100000 then begin\r\n      FLogsIsDel := True;\r\n      for I := 10000 downto 0 do\r\n        FLogs.Delete(I);  \r\n    end;\r\n    \/\/ \u6dfb\u52a0\u5f53\u524d\u65e5\u5fd7\u5185\u5bb9\r\n    FLogs.Add('[' + FormatDateTime('hh:mm:ss.zzz', Now) + '] ' + Log);\r\n    FLocker.Leave;\r\n    \/\/ \u4ea7\u751f\u4e00\u4e2a\u53d8\u66f4\u901a\u77e5\r\n    DoDataChange();\r\n  end;\r\nend;\r\n\r\n\/\/ \u521d\u59cb\u5316\r\nprocedure TForm1.FormCreate(Sender: TObject);\r\nbegin\r\n  FLogsIsDel := False;\r\n  FLogRef := 0;\r\n  FTestRef := 0;\r\n  FLogs := TStringList.Create();\r\n  FLocker := TCriticalSection.Create;\r\n  FAutoScroll := CheckBox1.Checked;\r\n  \/\/ \u5c06\u6700\u5927\u5de5\u4f5c\u8005\u6570\u91cf\u8bbe\u7f6e\u5927\u4e00\u4e9b\u3002\u56e0\u4e3a\u592a\u5c11\u7684\u8bdd\uff0c\u5de5\u4f5c\u8005\u4e0d\u591f\u7528\uff0c\u6ca1\u6709\u65f6\u95f4\u6765\u663e\u793a\u65e5\u5fd7\u4e86\u3002\r\n  Workers.MaxWorkers := 512;\r\nend;\r\n\r\nprocedure TForm1.FormDestroy(Sender: TObject);\r\nbegin\r\n  Workers.Clear(Self);\r\n  FreeAndNil(FLogs);\r\n  FreeAndNil(FLocker);\r\nend;\r\n\r\nprocedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);\r\nbegin\r\n  FLocker.Enter;\r\n  if Assigned(FLogs) and (Item.Index &lt; FLogs.Count) then\r\n    Item.Caption := FLogs[Item.Index];\r\n  FLocker.Leave;\r\nend;\r\n\r\nprocedure TForm1.Log(const Text: string);\r\nbegin\r\n  if Assigned(Self) then    \r\n    DoWriteLog(Self, Text);\r\nend;\r\n\r\nprocedure TForm1.OnDataChange(AJob: PJob);\r\nbegin\r\n  if Assigned(Self) and Assigned(FLogs) then begin\r\n    if Assigned(ListView1) and (ListView1.HandleAllocated = True) then begin\r\n      ListView_SetItemCountEx(ListView1.Handle, FLogs.Count,\r\n        LVSICF_NOINVALIDATEALL or LVSICF_NOSCROLL); \/\/ \u4fee\u6539\u5217\u8868\u9879\u7684\u6570\u91cf\uff0c\u5e76\u4e0d\u6539\u53d8\u6eda\u52a8\u6761\u4f4d\u7f6e\r\n      if FAutoScroll then\r\n        SendMessage(ListView1.Handle, WM_VSCROLL, SB_BOTTOM, 0);\r\n      if FLogsIsDel then begin\r\n        FLogsIsDel := False;\r\n        ListView1.Invalidate;\r\n      end;\r\n    end;\r\n    InterlockedDecrement(FLogRef);\r\n  end;\r\nend;\r\n\r\nend.\r\n<\/pre>\n<p>\u6838\u5fc3\u6709\u4e24\u70b9\uff1a<\/p>\n<ol>\n<li>\u00a0\u4f7f\u7528FLogRef\u8ba1\u7b97\u5668\u4f5c\u4e3a\u5b9e\u9645\u66f4\u65b0\u754c\u9762\u7684\u4f9d\u636e\u3002<\/li>\n<li>\u4f7f\u7528ListView_SetItemCountEx\u5b8f\u6765\u4ee3\u66ffListView.Count=xxxx\u66f4\u65b0\u5217\u8868\u6846\u7684\u884c\u6570\u3002<\/li>\n<li>\u4f7f\u7528\u4e34\u754c\u9501\u6765\u4fdd\u6301\u7ebf\u7a0b\u540c\u6b65\u3002<\/li>\n<\/ol>\n<p>\u6e90\u7801\u4e0b\u8f7d\uff1a<\/p>\n<p><a href=\"https:\/\/blog.qdac.cc\/?attachment_id=3496\" rel=\"attachment wp-att-3496\">LogView_Demo<\/a><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u8981\u89e3\u51b3\u7684\u95ee\u9898\uff1a \u6709\u591a\u4e2a\u7ebf\u7a0b\u8f93\u51fa\u65e5\u5fd7\uff0c\u65e5\u5fd7 [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[8,6],"tags":[449,34,20],"class_list":["post-3492","post","type-post","status-publish","format-standard","hentry","category-delphi","category-qworker","tag-qworker","tag-yxdworker","tag-20"],"views":5513,"_links":{"self":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts\/3492","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3492"}],"version-history":[{"count":2,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts\/3492\/revisions"}],"predecessor-version":[{"id":3498,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts\/3492\/revisions\/3498"}],"wp:attachment":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3492"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3492"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3492"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}