Language
Note
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãµã€ã³ã€ã³ãŸãã¯ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ã¿ã¹ã¯äžŠåã©ã€ãã©ãª (TPL) ã«ã¯ãã³ã³ã«ã¬ã³ã·ãŒãæå¹ãªã¢ããªã±ãŒã·ã§ã³ã®å ç¢æ§ãé«ããã®ã«åœ¹ç«ã€ããŒã¿ãã㌠ã³ã³ããŒãã³ããçšæãããŠããŸãã ãããã®ããŒã¿ãã㌠ã³ã³ããŒãã³ãã¯ããŸãšã㊠TPL ããŒã¿ãã㌠ã©ã€ãã©ãªãšåŒã°ããŸãã ãã®ããŒã¿ãã㌠ã¢ãã«ã¯ãç²ãããŒã¿ãããŒããã³ãã€ãã©ã€ã³åŠçã¿ã¹ã¯ã«å¯ŸããŠã€ã³ããã»ã¹ ã¡ãã»ãŒãž ã®åãæž¡ããæäŸããããšã§ãã¢ã¯ã¿ãŒããŒã¹ã®ããã°ã©ãã³ã°ãä¿é²ããŸãã ããŒã¿ãã㌠ã³ã³ããŒãã³ãã¯ãTPL ã®åãšã¹ã±ãžã¥ãŒã« ã€ã³ãã©ã¹ãã©ã¯ãã£ã«åºã¥ããŠæ§ç¯ãããéåæããã°ã©ãã³ã°ã®ããã® C#ãVisual BasicãF# èšèªã®ãµããŒããšçµ±åãããŸãã ãããã®ããŒã¿ãã㌠ã³ã³ããŒãã³ãã¯ãéåæçã«çžäºã«éä¿¡ããå¿ èŠãããè€æ°ã®æäœãããå ŽåããããŒã¿ã䜿çšå¯èœã«ãªã£ããšãã«åŠçããå¿ èŠãããå Žåã«äŸ¿å©ã§ãã ããšãã°ãWeb ã«ã¡ã©ããç»åããŒã¿ãåŠçããã¢ããªã±ãŒã·ã§ã³ãèããŠã¿ãŸãããã ããŒã¿ãã㌠ã¢ãã«ã䜿çšããããšã§ãã¢ããªã±ãŒã·ã§ã³ã¯ã€ã¡ãŒãž ãã¬ãŒã ã䜿çšå¯èœã«ãªã£ããšãã«åŠçã§ããŸãã ã¢ããªã±ãŒã·ã§ã³ã§ç»åãã¬ãŒã ãæ¡åŒµããå Žå (ããšãã°ãå è£æ£ãèµ€ç®é€å»ãå®è¡ãããªã©)ãããŒã¿ãã㌠ã³ã³ããŒãã³ãã® ãã€ãã©ã€ã³ ãäœæã§ããŸãã ãã€ãã©ã€ã³ã®åã¹ããŒãžã§ã¯ãTPL ã«ãã£ãŠæäŸãããæ©èœãªã©ãããç²ã䞊ååŠçæ©èœã䜿çšããŠã€ã¡ãŒãžã倿ããå ŽåããããŸãã
ãã®ããã¥ã¡ã³ãã§ã¯ãTPL ããŒã¿ãã㌠ã©ã€ãã©ãªã®æŠèŠã«ã€ããŠèª¬æããŸãã ããã°ã©ãã³ã° ã¢ãã«ãå®çŸ©æžã¿ã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡ãããã³ã¢ããªã±ãŒã·ã§ã³ã®ç¹å®ã®èŠä»¶ãæºããããã«ããŒã¿ãã㌠ãããã¯ãæ§æããæ¹æ³ã«ã€ããŠèª¬æããŸãã
泚
TPL ããŒã¿ãã㌠ã©ã€ãã©ãª ( System.Threading.Tasks.Dataflow åå空é) ã¯ã.NET 6 以éã®ããŒãžã§ã³ã«å«ãŸããŠããŸãã .NET Framework ããã³ .NET Standard ãããžã§ã¯ãã®å Žåã¯ã ðŠ System.Threading.Tasks.Dataflow NuGet ããã±ãŒãžãã€ã³ã¹ããŒã«ããå¿ èŠããããŸãã
ããã°ã©ãã³ã° ã¢ãã«
TPL ããŒã¿ãã㌠ã©ã€ãã©ãªã¯ãé«ã¹ã«ãŒãããã§åŸ æ©æéãçããCPU è² è·ã®é«ã I/O éäžåã¢ããªã±ãŒã·ã§ã³ãã¡ãã»ãŒãžãæž¡ããŠäžŠååããããã®åºç€ãæäŸããŸãã ãŸããããŒã¿ã®ãããã¡ãªã³ã°æ¹æ³ãšã·ã¹ãã å ã®ç§»åæ¹æ³ãæç€ºçã«å¶åŸ¡ããããšãã§ããŸãã ããŒã¿ãã㌠ããã°ã©ãã³ã° ã¢ãã«ã«ã€ããŠçè§£ãæ·±ããããã«ããã£ã¹ã¯ããã€ã¡ãŒãžãéåæçã«èªã¿èŸŒã¿ããããã®ã€ã¡ãŒãžã®è€åãäœæããã¢ããªã±ãŒã·ã§ã³ãæ€èšããŠãã ããã åŸæ¥ã®ããã°ã©ãã³ã° ã¢ãã«ã§ã¯ãéåžžãã¿ã¹ã¯ãšå ±æããŒã¿ãžã®ã¢ã¯ã»ã¹ã調æŽããããã«ãã³ãŒã«ããã¯ãšåæãªããžã§ã¯ã (ããã¯ãªã©) ã䜿çšããå¿ èŠããããŸãã ããŒã¿ãã㌠ããã°ã©ãã³ã° ã¢ãã«ã䜿çšãããšãã€ã¡ãŒãžããã£ã¹ã¯ããèªã¿åãéã«åŠçããããŒã¿ãã㌠ãªããžã§ã¯ããäœæã§ããŸãã ããŒã¿ãã㌠ã¢ãã«ã§ã¯ã䜿çšå¯èœã«ãªã£ããšãã®ããŒã¿ã®åŠçæ¹æ³ãšãããŒã¿éã®äŸåé¢ä¿ã宣èšããŸãã ã©ã³ã¿ã€ã ã¯ããŒã¿éã®äŸåé¢ä¿ã管çãããããå€ãã®å Žåãå ±æããŒã¿ãžã®ã¢ã¯ã»ã¹ãåæããèŠä»¶ãåé¿ã§ããŸãã ããã«ãã©ã³ã¿ã€ã ã¯ããŒã¿ã®éåæå°çã«åºã¥ããŠåäœãã¹ã±ãžã¥ãŒã«ãããããåºã«ãªãã¹ã¬ãããå¹ççã«ç®¡çããããšã§ãããŒã¿ãããŒã®å¿çæ§ãšã¹ã«ãŒããããåäžãããããšãã§ããŸãã ããŒã¿ãã㌠ããã°ã©ãã³ã° ã¢ãã«ã䜿çšã㊠Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã«ç»ååŠçãå®è£ ããäŸã«ã€ããŠã¯ãã ãã¥ãŒããªã¢ã«: Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã§ã®ããŒã¿ãããŒã®äœ¿çšããåç §ããŠãã ããã
ãœãŒã¹ãšã¿ãŒã²ãã
TPL ããŒã¿ãã㌠ã©ã€ãã©ãªã¯ãããŒã¿ããããã¡ãŒåŠçããŠåŠçããããŒã¿æ§é ã§ããããŒã¿ ãã㌠ãããã¯ã§æ§æãããŸãã TPL ã¯ã ãœãŒã¹ ãããã¯ã ã¿ãŒã²ãã ãããã¯ãäŒéåãããã¯ã® 3 çš®é¡ã®ããŒã¿ãã㌠ãããã¯ãå®çŸ©ããŸãã ãœãŒã¹ ãããã¯ã¯ããŒã¿ã®ãœãŒã¹ãšããŠæ©èœããããããèªã¿åãããšãã§ããŸãã ã¿ãŒã²ãã ãããã¯ã¯ããŒã¿ã®åä¿¡è ãšããŠæ©èœããæžã蟌ãããšãã§ããŸãã äŒéåãããã¯ã¯ããœãŒã¹ ãããã¯ãšã¿ãŒã²ãã ãããã¯ã®äž¡æ¹ãšããŠæ©èœããèªã¿åããšæžã蟌ã¿ãè¡ãããšãã§ããŸãã TPL ã¯ããœãŒã¹ã衚ã System.Threading.Tasks.Dataflow.ISourceBlock<TOutput> ã€ã³ã¿ãŒãã§ã€ã¹ãã¿ãŒã²ããã衚ã System.Threading.Tasks.Dataflow.ITargetBlock<TInput> ãäŒéåã衚ã System.Threading.Tasks.Dataflow.IPropagatorBlock<TInput,TOutput> ãå®çŸ©ããŸãã IPropagatorBlock<TInput,TOutput> ã¯ã ISourceBlock<TOutput>ãš ITargetBlock<TInput>ã®äž¡æ¹ããç¶æ¿ãããŸãã
TPL ããŒã¿ãã㌠ã©ã€ãã©ãªã«ã¯ã ISourceBlock<TOutput>ã ITargetBlock<TInput>ãããã³ IPropagatorBlock<TInput,TOutput> ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããå®çŸ©æžã¿ã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡ãããã€ãçšæãããŠããŸãã ãããã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡ã«ã€ããŠã¯ããã®ããã¥ã¡ã³ãã®ã å®çŸ©æžã¿ã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡ãã»ã¯ã·ã§ã³ã§èª¬æããŸãã
ãããã¯ã®æ¥ç¶
ããŒã¿ãã㌠ãããã¯ãæ¥ç¶ããŠãããŒã¿ãã㌠ãããã¯ã®ç·åœ¢ã·ãŒã±ã³ã¹ã§ãã ãã€ãã©ã€ã³ããŸãã¯ããŒã¿ãã㌠ãããã¯ã®ã°ã©ãã§ãã ãããã¯ãŒã¯ã圢æã§ããŸãã ãã€ãã©ã€ã³ã¯ãããã¯ãŒã¯ã® 1 ã€ã®åœ¢åŒã§ãã ãã€ãã©ã€ã³ãŸãã¯ãããã¯ãŒã¯ã§ã¯ããœãŒã¹ã¯ãããŒã¿ã䜿çšå¯èœã«ãªããšãéåæçã«ããŒã¿ãã¿ãŒã²ããã«äŒéããŸãã ISourceBlock<TOutput>.LinkTo ã¡ãœããã¯ããœãŒã¹ ããŒã¿ãã㌠ãããã¯ãã¿ãŒã²ãã ãããã¯ã«ãªã³ã¯ããŸãã ãœãŒã¹ã¯ã0 å以äžã®ã¿ãŒã²ããã«ãªã³ã¯ã§ããŸããã¿ãŒã²ããã¯ã0 å以äžã®ãœãŒã¹ãããªã³ã¯ã§ããŸãã ãã€ãã©ã€ã³ãŸãã¯ãããã¯ãŒã¯ã«å¯ŸããŠããŸãã¯ãã€ãã©ã€ã³ãŸãã¯ãããã¯ãŒã¯ããåæã«ããŒã¿ãã㌠ãããã¯ã远å ãŸãã¯åé€ã§ããŸãã å®çŸ©æžã¿ã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡ã¯ããªã³ã¯ãšãªã³ã¯è§£é€ã®ãã¹ãŠã®ã¹ã¬ãã ã»ãŒãã®åŽé¢ãåŠçããŸãã
ããŒã¿ãã㌠ãããã¯ãæ¥ç¶ããŠåºæ¬çãªãã€ãã©ã€ã³ã圢æããäŸã«ã€ããŠã¯ãã ãã¥ãŒããªã¢ã«: ããŒã¿ãã㌠ãã€ãã©ã€ã³ã®äœæããåç §ããŠãã ããã ããŒã¿ãã㌠ãããã¯ãæ¥ç¶ããŠããè€éãªãããã¯ãŒã¯ã圢æããäŸã«ã€ããŠã¯ãã ãã¥ãŒããªã¢ã«: Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã§ã®ããŒã¿ãããŒã®äœ¿çšããåç §ããŠãã ããã ãœãŒã¹ãã¿ãŒã²ããã«ã¡ãã»ãŒãžãæäŸããåŸã«ãœãŒã¹ããã¿ãŒã²ããã®ãªã³ã¯ãè§£é€ããäŸã«ã€ããŠã¯ãã æ¹æ³: ããŒã¿ãã㌠ãããã¯ã®ãªã³ã¯ãè§£é€ããããåç §ããŠãã ããã
ãã£ã«ã¿ãªã³ã°
ISourceBlock<TOutput>.LinkTo ã¡ãœãããåŒã³åºããŠãœãŒã¹ãã¿ãŒã²ããã«ãªã³ã¯ããå Žåããã®ã¡ãã»ãŒãžã®å€ã«åºã¥ããŠã¿ãŒã²ãã ãããã¯ãã¡ãã»ãŒãžãåãå ¥ãããæåŠããããæ±ºå®ããããªã²ãŒããæå®ã§ããŸãã ãã®ãã£ã«ã¿ãŒåŠçã¡ã«ããºã ã¯ãããŒã¿ãã㌠ãããã¯ãç¹å®ã®å€ã®ã¿ãåãåã£ãŠããããšãä¿èšŒãã䟿å©ãªæ¹æ³ã§ãã å®çŸ©æžã¿ã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡ã®ã»ãšãã©ã§ããœãŒã¹ ãããã¯ãè€æ°ã®ã¿ãŒã²ãã ãããã¯ã«æ¥ç¶ãããŠããå Žåãã¿ãŒã²ãã ãããã¯ãã¡ãã»ãŒãžãæåŠãããšããœãŒã¹ã¯ãã®ã¡ãã»ãŒãžã次ã®ã¿ãŒã²ããã«æäŸããŸãã ãœãŒã¹ãã¿ãŒã²ããã«ã¡ãã»ãŒãžãæäŸããé åºã¯ããœãŒã¹ã«ãã£ãŠå®çŸ©ããããœãŒã¹ã®çš®é¡ã«ãã£ãŠç°ãªãå ŽåããããŸãã ã»ãšãã©ã®ãœãŒã¹ ãããã¯ã®çš®é¡ã¯ã1 ã€ã®ã¿ãŒã²ããããã®ã¡ãã»ãŒãžãåãå ¥ããåŸãã¡ãã»ãŒãžã®æäŸã忢ããŸãã ãã®èŠåã® 1 ã€ã®äŸå€ã¯ãäžéšã®ã¿ãŒã²ãããã¡ãã»ãŒãžãæåŠããå Žåã§ãããã¹ãŠã®ã¿ãŒã²ããã«åã¡ãã»ãŒãžãæäŸãã BroadcastBlock<T> ã¯ã©ã¹ã§ãã ãã£ã«ã¿ãŒåŠçã䜿çšããŠç¹å®ã®ã¡ãã»ãŒãžã®ã¿ãåŠçããäŸã«ã€ããŠã¯ãã ãã¥ãŒããªã¢ã«: Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã§ã®ããŒã¿ãããŒã®äœ¿çšããåç §ããŠãã ããã
Von Bedeutung
å®çŸ©æžã¿ã®åãœãŒã¹ ããŒã¿ãã㌠ãããã¯ã®çš®é¡ã§ã¯ãã¡ãã»ãŒãžãåä¿¡ããé åºã§äŒéãããããšãä¿èšŒããããããœãŒã¹ ãããã¯ã次ã®ã¡ãã»ãŒãžãåŠçããã«ã¯ããã¹ãŠã®ã¡ãã»ãŒãžããœãŒã¹ ãããã¯ããèªã¿åãå¿ èŠããããŸãã ãã®ããããã£ã«ã¿ãŒåŠçã䜿çšããŠè€æ°ã®ã¿ãŒã²ããããœãŒã¹ã«æ¥ç¶ããå Žåã¯ãå°ãªããšã 1 ã€ã®ã¿ãŒã²ãã ãããã¯ãåã¡ãã»ãŒãžãåä¿¡ããããšã確èªããŸãã ããããªããšãã¢ããªã±ãŒã·ã§ã³ããããããã¯ããå¯èœæ§ããããŸãã
ã¡ãã»ãŒãž ããã·ã³ã°
ããŒã¿ãã㌠ããã°ã©ãã³ã° ã¢ãã«ã¯ã ã¡ãã»ãŒãžã®åãæž¡ãã®æŠå¿µã«é¢é£ããŠããŸãããã®æŠå¿µã§ã¯ãããã°ã©ã ã®ç¬ç«ããã³ã³ããŒãã³ããã¡ãã»ãŒãžãéä¿¡ããããšã«ãã£ãŠçžäºã«éä¿¡ããŸãã ã¢ããªã±ãŒã·ã§ã³ ã³ã³ããŒãã³ãéã§ã¡ãã»ãŒãžãäŒéãã 1 ã€ã®æ¹æ³ã¯ã Post (åæ) ã¡ãœãããš SendAsync (éåæ) ã¡ãœãããåŒã³åºããŠã¿ãŒã²ãã ããŒã¿ãã㌠ãããã¯ã«ã¡ãã»ãŒãžãéä¿¡ãããœãŒã¹ ãããã¯ããã¡ãã»ãŒãžãåä¿¡ãã Receiveã ReceiveAsyncãããã³ TryReceive ã¡ãœãããåŒã³åºãããšã§ãã ãããã®ã¡ãœãããããŒã¿ãã㌠ãã€ãã©ã€ã³ãŸãã¯ãããã¯ãŒã¯ãšçµã¿åãããã«ã¯ãå ¥åããŒã¿ãããã ããŒã (ã¿ãŒã²ãã ãããã¯) ã«éä¿¡ãããã€ãã©ã€ã³ã®ã¿ãŒããã« ããŒããŸãã¯ãããã¯ãŒã¯ã®ã¿ãŒããã« ããŒã (1 ã€ä»¥äžã®ãœãŒã¹ ãããã¯) ããåºåããŒã¿ãåä¿¡ããŸãã ãŸãã Choose ã¡ãœããã䜿çšããŠãæäŸãããŠããæåã®ãœãŒã¹ããããŒã¿ãèªã¿åãããã®ããŒã¿ã«å¯ŸããŠã¢ã¯ã·ã§ã³ãå®è¡ããããšãã§ããŸãã
ãœãŒã¹ ãããã¯ã¯ã ITargetBlock<TInput>.OfferMessage ã¡ãœãããåŒã³åºãããšã«ãã£ãŠãã¿ãŒã²ãã ãããã¯ã«ããŒã¿ãæäŸããŸãã ã¿ãŒã²ãã ãããã¯ã¯ãã¡ãã»ãŒãžã®åãå ¥ããã¡ãã»ãŒãžã®æåŠããŸãã¯ã¡ãã»ãŒãžã®å»¶æã®ããããã®æ¹æ³ã§ãæäŸãããã¡ãã»ãŒãžã«å¿çããŸãã ã¿ãŒã²ãããã¡ãã»ãŒãžãåãå ¥ãããšã OfferMessage ã¡ãœãã㯠Acceptedãè¿ããŸãã ã¿ãŒã²ãããã¡ãã»ãŒãžãæåŠãããšã OfferMessage ã¡ãœãã㯠Declinedãè¿ããŸãã ã¿ãŒã²ããããœãŒã¹ããã¡ãã»ãŒãžãåä¿¡ããªããªã£ãããšãå¿ èŠãªå Žåã OfferMessage 㯠DecliningPermanentlyãè¿ããŸãã å®çŸ©æžã¿ã®ãœãŒã¹ ãããã¯ã®çš®é¡ã¯ããã®ãããªæ»ãå€ãåä¿¡ããåŸã«ãªã³ã¯ãããã¿ãŒã²ããã«ã¡ãã»ãŒãžãæäŸããããã®ãããªã¿ãŒã²ããããã®ãªã³ã¯ãèªåçã«è§£é€ããŸãã
ã¿ãŒã²ãã ãããã¯ãåŸã§äœ¿çšããããã«ã¡ãã»ãŒãžãå»¶æãããšã OfferMessage ã¡ãœãã㯠Postponedãè¿ããŸãã ã¡ãã»ãŒãžãå»¶æããã¿ãŒã²ãã ãããã¯ã¯ãåŸã§ ISourceBlock<TOutput>.ReserveMessage ã¡ãœãããåŒã³åºããŠãæäŸãããã¡ãã»ãŒãžã®äºçŽã詊ã¿ãããšãã§ããŸãã ãã®æç¹ã§ãã¡ãã»ãŒãžã¯åŒãç¶ã䜿çšå¯èœã§ãããã¿ãŒã²ãã ãããã¯ã§äœ¿çšã§ãããããŸãã¯ã¡ãã»ãŒãžãå¥ã®ã¿ãŒã²ããã«ãã£ãŠååŸãããŠããŸãã ã¿ãŒã²ãã ãããã¯ã¯ãåŸã§ã¡ãã»ãŒãžãå¿ èŠãšããå ŽåããŸãã¯ã¡ãã»ãŒãžãäžèŠã«ãªã£ãå Žåã¯ããããã ISourceBlock<TOutput>.ConsumeMessage ãŸã㯠ReleaseReservation ã¡ãœãããåŒã³åºããŸãã ã¡ãã»ãŒãžäºçŽã¯éåžžãé貪欲ã¢ãŒãã§åäœããããŒã¿ãããŒãããã¯ã®çš®é¡ã«ãã£ãŠäœ¿çšãããŸãã é貪欲ã¢ãŒãã«ã€ããŠã¯ããã®ããã¥ã¡ã³ãã®åŸåã§èª¬æããŸãã ã¿ãŒã²ãã ãããã¯ã§ã¯ãå»¶æãããã¡ãã»ãŒãžãäºçŽãã代ããã«ã ISourceBlock<TOutput>.ConsumeMessage ã¡ãœããã䜿çšããŠãå»¶æãããã¡ãã»ãŒãžãçŽæ¥äœ¿çšããããšãã§ããŸãã
ããŒã¿ãã㌠ãããã¯ã®å®äº
ããŒã¿ãã㌠ãããã¯ã§ã¯ ãå®äºã®æŠå¿µããµããŒããããŠããŸãã å®äºç¶æ ã®ããŒã¿ãã㌠ãããã¯ã§ã¯ããã以äžã®åŠçã¯å®è¡ãããŸããã åããŒã¿ãã㌠ãããã¯ã«ã¯ãããã㯠System.Threading.Tasks.Task å®äºç¶æ ã衚ã å®äºã¿ã¹ã¯ãšåŒã°ãããªããžã§ã¯ããé¢é£ä»ããããŠããŸãã Task ãªããžã§ã¯ããå®äºãããŸã§åŸ æ©ã§ãããããå®äºã¿ã¹ã¯ã䜿çšããŠãããŒã¿ãã㌠ãããã¯ãŒã¯ã® 1 ã€ä»¥äžã®ã¿ãŒããã« ããŒããå®äºããã®ãåŸ ã€ããšãã§ããŸãã IDataflowBlock ã€ã³ã¿ãŒãã§ã€ã¹ã¯ãCompleteã¡ãœãããå®çŸ©ããŸãããã®ã¡ãœããã¯ãå®äºããèŠæ±ãããŒã¿ãã㌠ãããã¯ã«éç¥ããããŒã¿ãã㌠ãããã¯ã®å®äºã¿ã¹ã¯ãè¿ã Completion ããããã£ãå®çŸ©ããŸãã ISourceBlock<TOutput>ãšITargetBlock<TInput>ã®äž¡æ¹ãIDataflowBlock ã€ã³ã¿ãŒãã§ã€ã¹ãç¶æ¿ããŸãã
ããŒã¿ãã㌠ãããã¯ããšã©ãŒãªãã§å®äºãããã1 ã€ä»¥äžã®ãšã©ãŒãçºçããããåãæ¶ããããã倿ããã«ã¯ã2 ã€ã®æ¹æ³ããããŸãã æåã®æ¹æ³ã¯ãTask.Waittry- ããã㯠(Visual Basic ã§catchTry-) ã®å®äºã¿ã¹ã¯ã«å¯ŸããŠCatch ã¡ãœãããåŒã³åºãæ¹æ³ã§ãã æ¬¡ã®äŸã§ã¯ãå
¥åå€ã 0 æªæºã®å Žåã«ActionBlock<TInput>ãã¹ããŒããArgumentOutOfRangeException ãªããžã§ã¯ããäœæããŸãã ãã®äŸã§ã¯ãå®äºã¿ã¹ã¯ã§ AggregateException ãåŒã³åºããšãWait ãã¹ããŒãããŸãã
ArgumentOutOfRangeExceptionã«ã¯ãInnerExceptions ãªããžã§ã¯ãã® AggregateException ããããã£ã䜿çšããŠã¢ã¯ã»ã¹ããŸãã
// Create an ActionBlock<int> object that prints its input
// and throws ArgumentOutOfRangeException if the input
// is less than zero.
var throwIfNegative = new ActionBlock<int>(n =>
{
Console.WriteLine($"n = {n}");
if (n < 0)
{
throw new ArgumentOutOfRangeException();
}
});
// Post values to the block.
throwIfNegative.Post(0);
throwIfNegative.Post(-1);
throwIfNegative.Post(1);
throwIfNegative.Post(-2);
throwIfNegative.Complete();
// Wait for completion in a try/catch block.
try
{
throwIfNegative.Completion.Wait();
}
catch (AggregateException ae)
{
// If an unhandled exception occurs during dataflow processing, all
// exceptions are propagated through an AggregateException object.
ae.Handle(e =>
{
Console.WriteLine($"Encountered {e.GetType().Name}: {e.Message}");
return true;
});
}
/* Output:
n = 0
n = -1
Encountered ArgumentOutOfRangeException: Specified argument was out of the range
of valid values.
*/
' Create an ActionBlock<int> object that prints its input
' and throws ArgumentOutOfRangeException if the input
' is less than zero.
Dim throwIfNegative = New ActionBlock(Of Integer)(Sub(n)
Console.WriteLine("n = {0}", n)
If n < 0 Then
Throw New ArgumentOutOfRangeException()
End If
End Sub)
' Post values to the block.
throwIfNegative.Post(0)
throwIfNegative.Post(-1)
throwIfNegative.Post(1)
throwIfNegative.Post(-2)
throwIfNegative.Complete()
' Wait for completion in a try/catch block.
Try
throwIfNegative.Completion.Wait()
Catch ae As AggregateException
' If an unhandled exception occurs during dataflow processing, all
' exceptions are propagated through an AggregateException object.
ae.Handle(Function(e)
Console.WriteLine("Encountered {0}: {1}", e.GetType().Name, e.Message)
Return True
End Function)
End Try
' Output:
' n = 0
' n = -1
' Encountered ArgumentOutOfRangeException: Specified argument was out of the range
' of valid values.
'
ãã®äŸã§ã¯ãå®è¡ããŒã¿ãã㌠ãããã¯ã®ããªã²ãŒãã§äŸå€ãåŠçãããªãã±ãŒã¹ã瀺ããŸãã ãã®ãããªãããã¯ã®æ¬äœã§äŸå€ãåŠçããããšããå§ãããŸãã ãã ãããããè¡ãããšãã§ããªãå Žåããããã¯ã¯åãæ¶ããããã®ããã«åäœããåä¿¡ã¡ãã»ãŒãžãåŠçããŸããã
ããŒã¿ãã㌠ãããã¯ãæç€ºçã«åãæ¶ããããšãAggregateException ãªããžã§ã¯ãã«ã¯ OperationCanceledException ããããã£ã«InnerExceptionsãå«ãŸããŸãã ããŒã¿ãããŒã®åãæ¶ãã®è©³çްã«ã€ããŠã¯ãã ãã£ã³ã»ã«ã®æå¹å ãã»ã¯ã·ã§ã³ãåç §ããŠãã ããã
ããŒã¿ãã㌠ãããã¯ã®å®äºç¶æ ã確èªãã 2 ã€ç®ã®æ¹æ³ã¯ãå®äºã¿ã¹ã¯ã®ç¶ç¶ã䜿çšããããC# ãš Visual Basic ã®éåæèšèªæ©èœã䜿çšããŠå®äºã¿ã¹ã¯ãéåæçã«åŸ æ©ããããšã§ãã Task.ContinueWith ã¡ãœããã«æå®ããããªã²ãŒãã¯ãç¶ç¶å ã¿ã¹ã¯ã衚ãTask ãªããžã§ã¯ããåãåããŸãã Completion ããããã£ã®å Žåãç¶ç¶ã®ããªã²ãŒãã¯å®äºã¿ã¹ã¯èªäœãåãåããŸãã æ¬¡ã®äŸã¯åã®äŸã«äŒŒãŠããŸããã ContinueWith ã¡ãœããã䜿çšããŠãããŒã¿ãããŒæäœå šäœã®ç¶æ ãåºåããç¶ç¶ã¿ã¹ã¯ãäœæããŸãã
// Create an ActionBlock<int> object that prints its input
// and throws ArgumentOutOfRangeException if the input
// is less than zero.
var throwIfNegative = new ActionBlock<int>(n =>
{
Console.WriteLine($"n = {n}");
if (n < 0)
{
throw new ArgumentOutOfRangeException();
}
});
// Create a continuation task that prints the overall
// task status to the console when the block finishes.
throwIfNegative.Completion.ContinueWith(task =>
{
Console.WriteLine($"The status of the completion task is '{task.Status}'.");
});
// Post values to the block.
throwIfNegative.Post(0);
throwIfNegative.Post(-1);
throwIfNegative.Post(1);
throwIfNegative.Post(-2);
throwIfNegative.Complete();
// Wait for completion in a try/catch block.
try
{
throwIfNegative.Completion.Wait();
}
catch (AggregateException ae)
{
// If an unhandled exception occurs during dataflow processing, all
// exceptions are propagated through an AggregateException object.
ae.Handle(e =>
{
Console.WriteLine($"Encountered {e.GetType().Name}: {e.Message}");
return true;
});
}
/* Output:
n = 0
n = -1
The status of the completion task is 'Faulted'.
Encountered ArgumentOutOfRangeException: Specified argument was out of the range
of valid values.
*/
' Create an ActionBlock<int> object that prints its input
' and throws ArgumentOutOfRangeException if the input
' is less than zero.
Dim throwIfNegative = New ActionBlock(Of Integer)(Sub(n)
Console.WriteLine("n = {0}", n)
If n < 0 Then
Throw New ArgumentOutOfRangeException()
End If
End Sub)
' Create a continuation task that prints the overall
' task status to the console when the block finishes.
throwIfNegative.Completion.ContinueWith(Sub(task) Console.WriteLine("The status of the completion task is '{0}'.", task.Status))
' Post values to the block.
throwIfNegative.Post(0)
throwIfNegative.Post(-1)
throwIfNegative.Post(1)
throwIfNegative.Post(-2)
throwIfNegative.Complete()
' Wait for completion in a try/catch block.
Try
throwIfNegative.Completion.Wait()
Catch ae As AggregateException
' If an unhandled exception occurs during dataflow processing, all
' exceptions are propagated through an AggregateException object.
ae.Handle(Function(e)
Console.WriteLine("Encountered {0}: {1}", e.GetType().Name, e.Message)
Return True
End Function)
End Try
' Output:
' n = 0
' n = -1
' The status of the completion task is 'Faulted'.
' Encountered ArgumentOutOfRangeException: Specified argument was out of the range
' of valid values.
'
ç¶ç¶ã¿ã¹ã¯ã®æ¬æã§ IsCanceled ãªã©ã®ããããã£ã䜿çšããŠãããŒã¿ãã㌠ãããã¯ã®å®äºç¶æ ã«é¢ããè¿œå æ å ±ã確èªããããšãã§ããŸãã ç¶ç¶ã¿ã¹ã¯ããããããã£ã³ã»ã«ããšã©ãŒåŠçãšã©ã®ããã«é¢ä¿ãããã®è©³çްã«ã€ããŠã¯ããç¶ç¶ã¿ã¹ã¯ã䜿çšããã¿ã¹ã¯ã®é£çµãããã¿ã¹ã¯ã®ãã£ã³ã»ã«ããããã³ãäŸå€åŠçããåç §ããŠãã ããã
å®çŸ©æžã¿ã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡
TPL ããŒã¿ãã㌠ã©ã€ãã©ãªã«ã¯ãå®çŸ©æžã¿ã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡ãããã€ãçšæãããŠããŸãã ãããã®åã¯ã ãããã¡ãŒ ãããã¯ã å®è¡ãããã¯ã ã°ã«ãŒãåãããã¯ã® 3 ã€ã®ã«ããŽãªã«åãããŠããŸãã æ¬¡ã®ã»ã¯ã·ã§ã³ã§ã¯ããããã®ã«ããŽãªãæ§æãããããã¯ã®çš®é¡ã«ã€ããŠèª¬æããŸãã
ãããã¡ãªã³ã° ãããã¯
ãããã¡ãŒ ãããã¯ã¯ãããŒã¿ ã³ã³ã·ã¥ãŒããŒã䜿çšããããŒã¿ãä¿æããŸãã TPL ããŒã¿ãã㌠ã©ã€ãã©ãªã«ã¯ã System.Threading.Tasks.Dataflow.BufferBlock<T>ã System.Threading.Tasks.Dataflow.BroadcastBlock<T>ã System.Threading.Tasks.Dataflow.WriteOnceBlock<T>ã® 3 çš®é¡ã®ãããã¡ãªã³ã° ãããã¯ãçšæãããŠããŸãã
BufferBlock<T>
BufferBlock<T> ã¯ã©ã¹ã¯ãæ±çšéåæã¡ãã»ãŒãžã³ã°æ§é ã衚ããŸãã ãã®ã¯ã©ã¹ã¯ãè€æ°ã®ãœãŒã¹ããæžã蟌ãã ããè€æ°ã®ã¿ãŒã²ããããèªã¿åã£ããã§ããã¡ãã»ãŒãžã®å å ¥ãå åºã (FIFO) ãã¥ãŒãæ ŒçŽããŸãã ã¿ãŒã²ããã BufferBlock<T> ãªããžã§ã¯ãããã¡ãã»ãŒãžãåä¿¡ãããšããã®ã¡ãã»ãŒãžã¯ã¡ãã»ãŒãž ãã¥ãŒããåé€ãããŸãã ãã®ããã BufferBlock<T> ãªããžã§ã¯ãã¯è€æ°ã®ã¿ãŒã²ãããæã€ããšãã§ããŸãããåã¡ãã»ãŒãžãåä¿¡ããã¿ãŒã²ãã㯠1 ã€ã ãã§ãã BufferBlock<T> ã¯ã©ã¹ã¯ãè€æ°ã®ã¡ãã»ãŒãžãå¥ã®ã³ã³ããŒãã³ãã«æž¡ãå¿ èŠãããããã®ã³ã³ããŒãã³ããåã¡ãã»ãŒãžãåä¿¡ããå¿ èŠãããå Žåã«äŸ¿å©ã§ãã
次ã®åºæ¬çãªäŸã§ã¯ãInt32 ãªããžã§ã¯ãã«ããã€ãã®BufferBlock<T>å€ããã¹ããããã®ãªããžã§ã¯ããããããã®å€ãèªã¿åããŸãã
// Create a BufferBlock<int> object.
var bufferBlock = new BufferBlock<int>();
// Post several messages to the block.
for (int i = 0; i < 3; i++)
{
bufferBlock.Post(i);
}
// Receive the messages back from the block.
for (int i = 0; i < 3; i++)
{
Console.WriteLine(bufferBlock.Receive());
}
/* Output:
0
1
2
*/
' Create a BufferBlock<int> object.
Dim bufferBlock = New BufferBlock(Of Integer)()
' Post several messages to the block.
For i As Integer = 0 To 2
bufferBlock.Post(i)
Next i
' Receive the messages back from the block.
For i As Integer = 0 To 2
Console.WriteLine(bufferBlock.Receive())
Next i
' Output:
' 0
' 1
' 2
'
BufferBlock<T> ãªããžã§ã¯ãã«ã¡ãã»ãŒãžãæžã蟌ã¿ã ãªããžã§ã¯ãããã¡ãã»ãŒãžãèªã¿åãæ¹æ³ã瀺ãå®å šãªäŸã«ã€ããŠã¯ããæ¹æ³: ããŒã¿ãã㌠ãããã¯ãžã®ã¡ãã»ãŒãžã®æžã蟌ã¿ãšããŒã¿ãã㌠ãããã¯ããã®ã¡ãã»ãŒãžã®èªã¿åãããåç §ããŠãã ããã
ãããŒããã£ã¹ããããã¯<T>
BroadcastBlock<T> ã¯ã©ã¹ã¯ãè€æ°ã®ã¡ãã»ãŒãžãå¥ã®ã³ã³ããŒãã³ãã«æž¡ãå¿ èŠããããããã®ã³ã³ããŒãã³ãã«å¿ èŠãªã®ã¯ææ°ã®å€ã ãã§ããå Žåã«äŸ¿å©ã§ãã ãã®ã¯ã©ã¹ã¯ãã¡ãã»ãŒãžãè€æ°ã®ã³ã³ããŒãã³ãã«ãããŒããã£ã¹ãããå Žåã«ã䟿å©ã§ãã
次ã®åºæ¬çãªäŸã§ã¯ã Double å€ã BroadcastBlock<T> ãªããžã§ã¯ãã«ãã¹ãããŠããããã®ãªããžã§ã¯ããããã®å€ãè€æ°åèªã¿åããŸãã å€ã¯èªã¿åã£ãåŸ BroadcastBlock<T> ãªããžã§ã¯ãããåé€ãããªããããæ¯ååãå€ã䜿çšã§ããŸãã
// Create a BroadcastBlock<double> object.
var broadcastBlock = new BroadcastBlock<double>(null);
// Post a message to the block.
broadcastBlock.Post(Math.PI);
// Receive the messages back from the block several times.
for (int i = 0; i < 3; i++)
{
Console.WriteLine(broadcastBlock.Receive());
}
/* Output:
3.14159265358979
3.14159265358979
3.14159265358979
*/
' Create a BroadcastBlock<double> object.
Dim broadcastBlock = New BroadcastBlock(Of Double)(Nothing)
' Post a message to the block.
broadcastBlock.Post(Math.PI)
' Receive the messages back from the block several times.
For i As Integer = 0 To 2
Console.WriteLine(broadcastBlock.Receive())
Next i
' Output:
' 3.14159265358979
' 3.14159265358979
' 3.14159265358979
'
BroadcastBlock<T>ã䜿çšããŠè€æ°ã®ã¿ãŒã²ãã ãããã¯ã«ã¡ãã»ãŒãžããããŒããã£ã¹ãããæ¹æ³ã瀺ãå®å šãªäŸã«ã€ããŠã¯ããæ¹æ³: ããŒã¿ãã㌠ãããã¯ã§ã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ãæå®ããããåç §ããŠãã ããã
WriteOnceBlock<T>
WriteOnceBlock<T> ã¯ã©ã¹ã¯ãBroadcastBlock<T> ã¯ã©ã¹ã«äŒŒãŠããŸãããWriteOnceBlock<T> ãªããžã§ã¯ãã 1 åã ãæžã蟌ãããšãã§ããç¹ãç°ãªããŸãã WriteOnceBlock<T>㯠C# èªã¿åãå°çš (Visual Basic ã§ã¯ ReadOnly) ããŒã¯ãŒãã«äŒŒãŠãããšèããããšãã§ããŸãããã ããWriteOnceBlock<T> ãªããžã§ã¯ãã¯ãæ§ç¯æã§ã¯ãªãå€ãåãåã£ãåŸã«äžå€ã«ãªããŸãã BroadcastBlock<T> ã¯ã©ã¹ãšåæ§ã«ãã¿ãŒã²ãããWriteOnceBlock<T> ãªããžã§ã¯ãããã¡ãã»ãŒãžãåä¿¡ããŠãããã®ã¡ãã»ãŒãžã¯ãã®ãªããžã§ã¯ãããåé€ãããŸããã ãã®ãããè€æ°ã®ã¿ãŒã²ãããã¡ãã»ãŒãžã®ã³ããŒãåä¿¡ããŸãã WriteOnceBlock<T> ã¯ã©ã¹ã¯ãè€æ°ã®ã¡ãã»ãŒãžã®æåã®ã¡ãã»ãŒãžã®ã¿ãäŒéããå Žåã«äŸ¿å©ã§ãã
次ã®åºæ¬çãªäŸã§ã¯ãString ãªããžã§ã¯ãã«è€æ°ã®WriteOnceBlock<T>å€ããã¹ããããã®ãªããžã§ã¯ãããå€ãèªã¿åããŸãã WriteOnceBlock<T> ãªããžã§ã¯ã㯠1 åã ãæžã蟌ãããšãã§ãããããWriteOnceBlock<T> ãªããžã§ã¯ãã¯ã¡ãã»ãŒãžãåä¿¡ããåŸãåŸç¶ã®ã¡ãã»ãŒãžãç Žæ£ããŸãã
// Create a WriteOnceBlock<string> object.
var writeOnceBlock = new WriteOnceBlock<string>(null);
// Post several messages to the block in parallel. The first
// message to be received is written to the block.
// Subsequent messages are discarded.
Parallel.Invoke(
() => writeOnceBlock.Post("Message 1"),
() => writeOnceBlock.Post("Message 2"),
() => writeOnceBlock.Post("Message 3"));
// Receive the message from the block.
Console.WriteLine(writeOnceBlock.Receive());
/* Sample output:
Message 2
*/
' Create a WriteOnceBlock<string> object.
Dim writeOnceBlock = New WriteOnceBlock(Of String)(Nothing)
' Post several messages to the block in parallel. The first
' message to be received is written to the block.
' Subsequent messages are discarded.
Parallel.Invoke(Function() writeOnceBlock.Post("Message 1"), Function() writeOnceBlock.Post("Message 2"), Function() writeOnceBlock.Post("Message 3"))
' Receive the message from the block.
Console.WriteLine(writeOnceBlock.Receive())
' Sample output:
' Message 2
'
WriteOnceBlock<T>ã䜿çšããŠãå®äºããæåã®æäœã®å€ãåãåãæ¹æ³ã瀺ãå®å šãªäŸã«ã€ããŠã¯ããæ¹æ³: ããŒã¿ãã㌠ãããã¯ã®ãªã³ã¯ãè§£é€ããããåç §ããŠãã ããã
å®è¡ãããã¯
å®è¡ãããã¯ã¯ãåä¿¡ããããŒã¿ã®åéšåã«å¯ŸããŠãŠãŒã¶ãŒæå®ã®ããªã²ãŒããåŒã³åºããŸãã TPL ããŒã¿ãã㌠ã©ã€ãã©ãªã«ã¯ã ActionBlock<TInput>ã System.Threading.Tasks.Dataflow.TransformBlock<TInput,TOutput>ã System.Threading.Tasks.Dataflow.TransformManyBlock<TInput,TOutput>ã® 3 çš®é¡ã®å®è¡ãããã¯ãçšæãããŠããŸãã
ActionBlock<T>
ActionBlock<TInput> ã¯ã©ã¹ã¯ãããŒã¿ãåä¿¡ãããšãã«ããªã²ãŒããåŒã³åºãã¿ãŒã²ãã ãããã¯ã§ãã
ActionBlock<TInput> ãªããžã§ã¯ãã¯ãããŒã¿ã䜿çšå¯èœã«ãªã£ããšãã«éåæçã«å®è¡ãããããªã²ãŒããšèããŠãã ããã
ActionBlock<TInput> ãªããžã§ã¯ãã«æå®ããããªã²ãŒãã«ã¯ãAction<T>åãŸãã¯System.Func<TInput, Task>åãæå®ã§ããŸãã
ActionBlock<TInput>ã§Action<T> ãªããžã§ã¯ãã䜿çšãããšãããªã²ãŒããæ»ã£ããšãã«åå
¥åèŠçŽ ã®åŠçãå®äºãããšèŠãªãããŸãã
ActionBlock<TInput>ã§System.Func<TInput, Task> ãªããžã§ã¯ãã䜿çšãããšãè¿ãããTask ãªããžã§ã¯ããå®äºããå Žåã«ã®ã¿ãåå
¥åèŠçŽ ã®åŠçãå®äºãããšèŠãªãããŸãã ããã 2 ã€ã®ã¡ã«ããºã ã䜿çšãããšãåå
¥åèŠçŽ ã®åæåŠçãšéåæåŠçã®äž¡æ¹ã« ActionBlock<TInput> ã䜿çšã§ããŸãã
次ã®åºæ¬çãªäŸã§ã¯ãInt32 ãªããžã§ã¯ãã«è€æ°ã®ActionBlock<TInput>å€ããã¹ãããŸãã ActionBlock<TInput> ãªããžã§ã¯ãã¯ããããã®å€ãã³ã³ãœãŒã«ã«åºåããŸãã æ¬¡ã®äœ¿çšäŸã¯ããããã¯ãå®äºç¶æ ã«èšå®ãããã¹ãŠã®ããŒã¿ãã㌠ã¿ã¹ã¯ãå®äºãããŸã§åŸ æ©ããŸãã
// Create an ActionBlock<int> object that prints values
// to the console.
var actionBlock = new ActionBlock<int>(n => Console.WriteLine(n));
// Post several messages to the block.
for (int i = 0; i < 3; i++)
{
actionBlock.Post(i * 10);
}
// Set the block to the completed state and wait for all
// tasks to finish.
actionBlock.Complete();
actionBlock.Completion.Wait();
/* Output:
0
10
20
*/
' Create an ActionBlock<int> object that prints values
' to the console.
Dim actionBlock = New ActionBlock(Of Integer)(Function(n) WriteLine(n))
' Post several messages to the block.
For i As Integer = 0 To 2
actionBlock.Post(i * 10)
Next i
' Set the block to the completed state and wait for all
' tasks to finish.
actionBlock.Complete()
actionBlock.Completion.Wait()
' Output:
' 0
' 10
' 20
'
ActionBlock<TInput> ã¯ã©ã¹ã§ããªã²ãŒãã䜿çšããæ¹æ³ã瀺ãå®å šãªäŸã«ã€ããŠã¯ããæ¹æ³: ããŒã¿ãã㌠ãããã¯ãããŒã¿ãåä¿¡ãããšãã«ã¢ã¯ã·ã§ã³ãå®è¡ããããåç §ããŠãã ããã
TransformBlock<TInputãTOutput>
TransformBlock<TInput,TOutput> ã¯ã©ã¹ã¯ããœãŒã¹ãšã¿ãŒã²ããã®äž¡æ¹ãšããŠæ©èœããããšãé€ããActionBlock<TInput> ã¯ã©ã¹ã«äŒŒãŠããŸãã
TransformBlock<TInput,TOutput> ãªããžã§ã¯ãã«æž¡ãããªã²ãŒãã¯ãTOutputåã®å€ãè¿ããŸãã
TransformBlock<TInput,TOutput> ãªããžã§ã¯ãã«æå®ããããªã²ãŒãã«ã¯ãSystem.Func<TInput, TOutput>åãŸãã¯System.Func<TInput, Task<TOutput>>åãæå®ã§ããŸãã
TransformBlock<TInput,TOutput>ã§System.Func<TInput, TOutput> ãªããžã§ã¯ãã䜿çšãããšãããªã²ãŒããæ»ã£ããšãã«åå
¥åèŠçŽ ã®åŠçãå®äºãããšèŠãªãããŸãã
TransformBlock<TInput,TOutput>ã§äœ¿çšããSystem.Func<TInput, Task<TOutput>> ãªããžã§ã¯ãã䜿çšããå Žåãåå
¥åèŠçŽ ã®åŠçã¯ãè¿ãããTask<TResult> ãªããžã§ã¯ããå®äºãããšãã«ã®ã¿å®äºãããšèŠãªãããŸãã
ActionBlock<TInput>ãšåæ§ã«ãããã 2 ã€ã®ã¡ã«ããºã ã䜿çšããŠãåå
¥åèŠçŽ ã®åæåŠçãšéåæåŠçã®äž¡æ¹ã«TransformBlock<TInput,TOutput>ã䜿çšã§ããŸãã
次ã®åºæ¬çãªäŸã§ã¯ãå ¥åã®å¹³æ¹æ ¹ãèšç®ãã TransformBlock<TInput,TOutput> ãªããžã§ã¯ããäœæããŸãã TransformBlock<TInput,TOutput> ãªããžã§ã¯ãã¯Int32å€ãå ¥åãšããŠåãåããDoubleå€ãåºåãšããŠçæããŸãã
// Create a TransformBlock<int, double> object that
// computes the square root of its input.
var transformBlock = new TransformBlock<int, double>(n => Math.Sqrt(n));
// Post several messages to the block.
transformBlock.Post(10);
transformBlock.Post(20);
transformBlock.Post(30);
// Read the output messages from the block.
for (int i = 0; i < 3; i++)
{
Console.WriteLine(transformBlock.Receive());
}
/* Output:
3.16227766016838
4.47213595499958
5.47722557505166
*/
' Create a TransformBlock<int, double> object that
' computes the square root of its input.
Dim transformBlock = New TransformBlock(Of Integer, Double)(Function(n) Math.Sqrt(n))
' Post several messages to the block.
transformBlock.Post(10)
transformBlock.Post(20)
transformBlock.Post(30)
' Read the output messages from the block.
For i As Integer = 0 To 2
Console.WriteLine(transformBlock.Receive())
Next i
' Output:
' 3.16227766016838
' 4.47213595499958
' 5.47722557505166
'
Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã§ç»ååŠçãå®è¡ããããŒã¿ãã㌠ãããã¯ã®ãããã¯ãŒã¯ã§ TransformBlock<TInput,TOutput> ã䜿çšããå®å šãªäŸã«ã€ããŠã¯ãã ãã¥ãŒããªã¢ã«: Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã§ã®ããŒã¿ãããŒã®äœ¿çšããåç §ããŠãã ããã
TransformManyBlock<TInputãTOutput>
TransformManyBlock<TInput,TOutput> ã¯ã©ã¹ã¯TransformBlock<TInput,TOutput> ã¯ã©ã¹ã«äŒŒãŠããŸãããTransformManyBlock<TInput,TOutput>ã§ã¯ãåå
¥åå€ã«å¯Ÿã㊠1 ã€ã®åºåå€ã§ã¯ãªããåå
¥åå€ã«å¯Ÿã㊠0 å以äžã®åºåå€ãçæãããç¹ãç°ãªããŸãã
TransformManyBlock<TInput,TOutput> ãªããžã§ã¯ãã«æå®ããããªã²ãŒãã«ã¯ãSystem.Func<TInput, IEnumerable<TOutput>>åãŸãã¯System.Func<TInput, Task<IEnumerable<TOutput>>>åãæå®ã§ããŸãã
TransformManyBlock<TInput,TOutput>ã§System.Func<TInput, IEnumerable<TOutput>> ãªããžã§ã¯ãã䜿çšãããšãããªã²ãŒããæ»ã£ããšãã«åå
¥åèŠçŽ ã®åŠçãå®äºãããšèŠãªãããŸãã
TransformManyBlock<TInput,TOutput>ã§System.Func<TInput, Task<IEnumerable<TOutput>>> ãªããžã§ã¯ãã䜿çšããå Žåãåå
¥åèŠçŽ ã®åŠçã¯ãè¿ãããSystem.Threading.Tasks.Task<IEnumerable<TOutput>> ãªããžã§ã¯ããå®äºãããšãã«ã®ã¿å®äºãããšèŠãªãããŸãã
次ã®åºæ¬çãªäŸã§ã¯ãæååãåã ã®æåã·ãŒã±ã³ã¹ã«åå²ãã TransformManyBlock<TInput,TOutput> ãªããžã§ã¯ããäœæããŸãã TransformManyBlock<TInput,TOutput> ãªããžã§ã¯ãã¯Stringå€ãå ¥åãšããŠåãåããCharå€ãåºåãšããŠçæããŸãã
// Create a TransformManyBlock<string, char> object that splits
// a string into its individual characters.
var transformManyBlock = new TransformManyBlock<string, char>(
s => s.ToCharArray());
// Post two messages to the first block.
transformManyBlock.Post("Hello");
transformManyBlock.Post("World");
// Receive all output values from the block.
for (int i = 0; i < ("Hello" + "World").Length; i++)
{
Console.WriteLine(transformManyBlock.Receive());
}
/* Output:
H
e
l
l
o
W
o
r
l
d
*/
' Create a TransformManyBlock<string, char> object that splits
' a string into its individual characters.
Dim transformManyBlock = New TransformManyBlock(Of String, Char)(Function(s) s.ToCharArray())
' Post two messages to the first block.
transformManyBlock.Post("Hello")
transformManyBlock.Post("World")
' Receive all output values from the block.
For i As Integer = 0 To ("Hello" & "World").Length - 1
Console.WriteLine(transformManyBlock.Receive())
Next i
' Output:
' H
' e
' l
' l
' o
' W
' o
' r
' l
' d
'
TransformManyBlock<TInput,TOutput>ã䜿çšããŠãããŒã¿ãã㌠ãã€ãã©ã€ã³å ã®å ¥åããšã«è€æ°ã®ç¬ç«ããåºåãçæããå®å šãªäŸã«ã€ããŠã¯ãããã¥ãŒããªã¢ã«: ããŒã¿ãã㌠ãã€ãã©ã€ã³ã®äœæããåç §ããŠãã ããã
䞊ååŠçã®æ¬¡æ°
ãã¹ãŠã® ActionBlock<TInput>ã TransformBlock<TInput,TOutput>ãããã³ TransformManyBlock<TInput,TOutput> ãªããžã§ã¯ãã¯ããããã¯ã§åŠçã§ããç¶æ ã«ãªããŸã§å ¥åã¡ãã»ãŒãžããããã¡ãŒããŸãã æ¢å®ã§ã¯ããããã®ã¯ã©ã¹ã¯ã¡ãã»ãŒãžãåä¿¡ããé åºã§äžåºŠã« 1 ã€ã®ã¡ãã»ãŒãžã§åŠçããŸãã ãŸãã䞊ååŠçã®æ¬¡æ°ãæå®ããŠã ActionBlock<TInput>ã TransformBlock<TInput,TOutput> ãããã³ TransformManyBlock<TInput,TOutput> ãªããžã§ã¯ããè€æ°ã®ã¡ãã»ãŒãžãåæã«åŠçã§ããããã«ããããšãã§ããŸãã åæå®è¡ã®è©³çްã«ã€ããŠã¯ããã®ããã¥ã¡ã³ãã§åŸè¿°ããã䞊ååŠçã®æ¬¡æ°ã®æå®ãã»ã¯ã·ã§ã³ãåç §ããŠãã ããã å®è¡ããŒã¿ãã㌠ãããã¯ãäžåºŠã«è€æ°ã®ã¡ãã»ãŒãžãåŠçã§ããããã«äžŠååŠçã®æ¬¡æ°ãèšå®ããäŸã«ã€ããŠã¯ãã æ¹æ³: ããŒã¿ãã㌠ãããã¯ã§äžŠååŠçã®æ¬¡æ°ãæå®ããããåç §ããŠãã ããã
ããªã²ãŒãåã®æŠèŠ
次ã®è¡šã¯ããªããžã§ã¯ãã® ActionBlock<TInput>ã TransformBlock<TInput,TOutput>ãããã³ TransformManyBlock<TInput,TOutput> ã«æå®ã§ããããªã²ãŒãåããŸãšãããã®ã§ãã ãã®ããŒãã«ã§ã¯ãããªã²ãŒãåãåæçã«åäœãããéåæçã«åäœããããæå®ããŸãã
| ã¿ã€ã | åæããªã²ãŒãã¿ã€ã | éåæçãªããªã²ãŒãå |
|---|---|---|
| ActionBlock<TInput> | System.Action |
System.Func<TInput, Task> |
| TransformBlock<TInput,TOutput> | System.Func<TInput, TOutput> |
System.Func<TInput, Task<TOutput>> |
| TransformManyBlock<TInput,TOutput> | System.Func<TInput, IEnumerable<TOutput>> |
System.Func<TInput, Task<IEnumerable<TOutput>>> |
ãŸããå®è¡ãããã¯åãæäœãããšãã«ã©ã ãåŒã䜿çšããããšãã§ããŸãã å®è¡ãããã¯ã§ã©ã ãåŒã䜿çšããæ¹æ³ã瀺ãäŸã«ã€ããŠã¯ãã æ¹æ³: ããŒã¿ãã㌠ãããã¯ãããŒã¿ãåä¿¡ãããšãã«ã¢ã¯ã·ã§ã³ãå®è¡ããããåç §ããŠãã ããã
ãããã¯ã®ã°ã«ãŒãå
ã°ã«ãŒãåãããã¯ã¯ã1 ã€ä»¥äžã®ãœãŒã¹ããã®ããŒã¿ããããŸããŸãªå¶çŽã®äžã§çµåããŸãã TPL ããŒã¿ãã㌠ã©ã€ãã©ãªã«ã¯ã BatchBlock<T>ã JoinBlock<T1,T2>ã BatchedJoinBlock<T1,T2>ã® 3 çš®é¡ã®çµåãããã¯ãçšæãããŠããŸãã
BatchBlock<T>
BatchBlock<T> ã¯ã©ã¹ã¯ãããããšåŒã°ããäžé£ã®å ¥åããŒã¿ãåºåããŒã¿ã®é åã«çµåããŸãã BatchBlock<T> ãªããžã§ã¯ããäœæãããšãã«ãåãããã®ãµã€ãºãæå®ããŸãã BatchBlock<T> ãªããžã§ã¯ãã¯ãæå®ããæ°ã®å ¥åèŠçŽ ãåãåããšããããã®èŠçŽ ãå«ãé åãéåæçã«äŒéããŸãã BatchBlock<T> ãªããžã§ã¯ããå®äºç¶æ ã«èšå®ãããŠããŠãããããã圢æããã®ã«ååãªèŠçŽ ãå«ãŸããŠããªãå Žåã¯ãæ®ãã®å ¥åèŠçŽ ãå«ãæçµçãªé åãäŒéãããŸãã
BatchBlock<T> ã¯ã©ã¹ã¯è²ªæ¬²ã¢ãŒããŸãã¯é貪欲ã¢ãŒãã§åäœããŸãã æ¢å®ã®ã°ãªãŒãã£ãŒã¢ãŒãã§ã¯ãBatchBlock<T> ãªããžã§ã¯ãã¯æäŸããããã¹ãŠã®ã¡ãã»ãŒãžãåãå
¥ããæå®ããèŠçŽ æ°ãåãåã£ãåŸã«é
åãåºåããŸãã é貪欲ã¢ãŒãã§ã¯ãBatchBlock<T> ãªããžã§ã¯ãã¯ãååãªæ°ã®ãœãŒã¹ããã¡ãã»ãŒãžãæäŸãããŠãããã圢æããããŸã§ããã¹ãŠã®åä¿¡ã¡ãã»ãŒãžã®åŠçãå»¶æããŸãã éåžžã貪欲ã¢ãŒãã¯ãåŠçãªãŒããŒããããå°ãªããããé貪欲ã¢ãŒããããåªããããã©ãŒãã³ã¹ãçºæ®ããŸãã ãã ããã¢ãããã¯ãªæ¹æ³ã§è€æ°ã®ãœãŒã¹ããã®æ¶è²»ãã³ãŒãã£ããŒãããå¿
èŠãããå Žåã¯ãé貪欲ã¢ãŒãã䜿çšã§ããŸãã
Greedy ã³ã³ã¹ãã©ã¯ã¿ãŒã® False ãã©ã¡ãŒã¿ãŒã§dataflowBlockOptionsãBatchBlock<T>ã«èšå®ããŠãé貪欲ã¢ãŒããæå®ããŸãã
次ã®åºæ¬çãªäŸã§ã¯ããããå ã® 10 åã®èŠçŽ ãä¿æããInt32 ãªããžã§ã¯ãã«ããã€ãã®BatchBlock<T>å€ããã¹ãããŸãã ãã®äŸã§ã¯ããã¹ãŠã®å€ã BatchBlock<T>ãã確å®ã«äŒéãããããã«ã Complete ã¡ãœãããåŒã³åºããŸãã Complete ã¡ãœããã¯ãBatchBlock<T> ãªããžã§ã¯ããå®äºç¶æ ã«èšå®ãããããBatchBlock<T> ãªããžã§ã¯ãã¯æ®ãã®èŠçŽ ãæçµçãªããããšããŠäŒéããŸãã
// Create a BatchBlock<int> object that holds ten
// elements per batch.
var batchBlock = new BatchBlock<int>(10);
// Post several values to the block.
for (int i = 0; i < 13; i++)
{
batchBlock.Post(i);
}
// Set the block to the completed state. This causes
// the block to propagate out any remaining
// values as a final batch.
batchBlock.Complete();
// Print the sum of both batches.
Console.WriteLine($"The sum of the elements in batch 1 is {batchBlock.Receive().Sum()}.");
Console.WriteLine($"The sum of the elements in batch 2 is {batchBlock.Receive().Sum()}.");
/* Output:
The sum of the elements in batch 1 is 45.
The sum of the elements in batch 2 is 33.
*/
' Create a BatchBlock<int> object that holds ten
' elements per batch.
Dim batchBlock = New BatchBlock(Of Integer)(10)
' Post several values to the block.
For i As Integer = 0 To 12
batchBlock.Post(i)
Next i
' Set the block to the completed state. This causes
' the block to propagate out any remaining
' values as a final batch.
batchBlock.Complete()
' Print the sum of both batches.
Console.WriteLine("The sum of the elements in batch 1 is {0}.", batchBlock.Receive().Sum())
Console.WriteLine("The sum of the elements in batch 2 is {0}.", batchBlock.Receive().Sum())
' Output:
' The sum of the elements in batch 1 is 45.
' The sum of the elements in batch 2 is 33.
'
BatchBlock<T>ã䜿çšããŠããŒã¿ããŒã¹æ¿å ¥æäœã®å¹çãåäžãããå®å šãªäŸã«ã€ããŠã¯ãããã¥ãŒããªã¢ã«: BatchBlock ãš BatchedJoinBlock ã䜿çšããŠå¹çãåäžãããããåç §ããŠãã ããã
JoinBlock<T1ãT2ã...>
JoinBlock<T1,T2>ã¯ã©ã¹ãšJoinBlock<T1,T2,T3> ã¯ã©ã¹ã¯ãå ¥åèŠçŽ ãåéãããããã®èŠçŽ ãå«ãSystem.Tuple<T1,T2>ãŸãã¯System.Tuple<T1,T2,T3>ãªããžã§ã¯ããäŒéããŸãã JoinBlock<T1,T2>ã¯ã©ã¹ãšJoinBlock<T1,T2,T3> ã¯ã©ã¹ã¯ãITargetBlock<TInput>ããç¶æ¿ãããŸããã 代ããã«ãTarget1ãå®è£ ããããããã£ãTarget2ãTarget3ãããã³ITargetBlock<TInput>ãæäŸãããŸãã
BatchBlock<T>ãšåæ§ã«ãJoinBlock<T1,T2>ãšJoinBlock<T1,T2,T3>ã¯è²ªæ¬²ã¢ãŒããŸãã¯é貪欲ã¢ãŒãã§åäœããŸãã æ¢å®ã®ã°ãªãŒãã£ãŒã¢ãŒãã§ã¯ãJoinBlock<T1,T2> ãŸã㯠JoinBlock<T1,T2,T3> ãªããžã§ã¯ãã¯æäŸããããã¹ãŠã®ã¡ãã»ãŒãžãåãå ¥ããåã¿ãŒã²ãããå°ãªããšã 1 ã€ã®ã¡ãã»ãŒãžãåä¿¡ããåŸã«ã¿ãã«ãéä¿¡ããŸãã é貪欲ã¢ãŒãã§ã¯ãJoinBlock<T1,T2> ãŸã㯠JoinBlock<T1,T2,T3> ãªããžã§ã¯ãã¯ãã¿ãã«ã®äœæã«å¿ èŠãªããŒã¿ããã¹ãŠã®ã¿ãŒã²ããã«æäŸããããŸã§ããã¹ãŠã®åä¿¡ã¡ãã»ãŒãžãå»¶æããŸãã ãã®æç¹ã§ããããã¯ã¯ 2 ãã§ãŒãº ã³ããã ãããã³ã«ã䜿çšããŠããœãŒã¹ããå¿ èŠãªãã¹ãŠã®é ç®ãã¢ãããã¯ã«ååŸããŸãã ãã®å»¶æã«ãããå¥ã®ãšã³ãã£ãã£ããããŸã§ã®éã«ããŒã¿ã䜿çšããŠãã·ã¹ãã å šäœãåé²ã§ããããã«ãªããŸãã
次ã®åºæ¬çãªäŸã¯ã JoinBlock<T1,T2,T3> ãªããžã§ã¯ããå€ãèšç®ããããã«è€æ°ã®ããŒã¿ãå¿ èŠãšããã±ãŒã¹ã瀺ããŠããŸãã æ¬¡ã®äœ¿çšäŸã¯ãç®è¡æŒç®ãå®è¡ããããã« 2 ã€ã®JoinBlock<T1,T2,T3>å€ãšInt32å€ãå¿ èŠãšããChar ãªããžã§ã¯ããäœæããŸãã
// Create a JoinBlock<int, int, char> object that requires
// two numbers and an operator.
var joinBlock = new JoinBlock<int, int, char>();
// Post two values to each target of the join.
joinBlock.Target1.Post(3);
joinBlock.Target1.Post(6);
joinBlock.Target2.Post(5);
joinBlock.Target2.Post(4);
joinBlock.Target3.Post('+');
joinBlock.Target3.Post('-');
// Receive each group of values and apply the operator part
// to the number parts.
for (int i = 0; i < 2; i++)
{
var data = joinBlock.Receive();
switch (data.Item3)
{
case '+':
Console.WriteLine($"{data.Item1} + {data.Item2} = {data.Item1 + data.Item2}");
break;
case '-':
Console.WriteLine($"{data.Item1} - {data.Item2} = {data.Item1 - data.Item2}");
break;
default:
Console.WriteLine($"Unknown operator '{data.Item3}'.");
break;
}
}
/* Output:
3 + 5 = 8
6 - 4 = 2
*/
' Create a JoinBlock<int, int, char> object that requires
' two numbers and an operator.
Dim joinBlock = New JoinBlock(Of Integer, Integer, Char)()
' Post two values to each target of the join.
joinBlock.Target1.Post(3)
joinBlock.Target1.Post(6)
joinBlock.Target2.Post(5)
joinBlock.Target2.Post(4)
joinBlock.Target3.Post("+"c)
joinBlock.Target3.Post("-"c)
' Receive each group of values and apply the operator part
' to the number parts.
For i As Integer = 0 To 1
Dim data = joinBlock.Receive()
Select Case data.Item3
Case "+"c
Console.WriteLine("{0} + {1} = {2}", data.Item1, data.Item2, data.Item1 + data.Item2)
Case "-"c
Console.WriteLine("{0} - {1} = {2}", data.Item1, data.Item2, data.Item1 - data.Item2)
Case Else
Console.WriteLine("Unknown operator '{0}'.", data.Item3)
End Select
Next i
' Output:
' 3 + 5 = 8
' 6 - 4 = 2
'
é貪欲ã¢ãŒãã§ JoinBlock<T1,T2> ãªããžã§ã¯ãã䜿çšããŠãªãœãŒã¹ãå調çã«å ±æããå®å šãªäŸã«ã€ããŠã¯ããæ¹æ³: JoinBlock ã䜿çšããŠè€æ°ã®ãœãŒã¹ããããŒã¿ãèªã¿åãããåç §ããŠãã ããã
BatchedJoinBlock<T1ãT2ã...>
BatchedJoinBlock<T1,T2>ã¯ã©ã¹ãšBatchedJoinBlock<T1,T2,T3> ã¯ã©ã¹ã¯ãå
¥åèŠçŽ ã®ããããåéãããããã®èŠçŽ ãå«ãSystem.Tuple(IList(T1), IList(T2))ãŸãã¯System.Tuple(IList(T1), IList(T2), IList(T3))ãªããžã§ã¯ããäŒéããŸãã
BatchedJoinBlock<T1,T2>ã¯ãBatchBlock<T>ãšJoinBlock<T1,T2>ã®çµã¿åãããšèããŠãã ããã
BatchedJoinBlock<T1,T2> ãªããžã§ã¯ããäœæãããšãã«ãåãããã®ãµã€ãºãæå®ããŸãã
BatchedJoinBlock<T1,T2>ã«ã¯ãTarget1ãå®è£
ãããããã㣠(Target2ãšITargetBlock<TInput>) ãçšæãããŠããŸãã æå®ããæ°ã®å
¥åèŠçŽ ããã¹ãŠã®ã¿ãŒã²ããããåä¿¡ããããšã BatchedJoinBlock<T1,T2> ãªããžã§ã¯ãã¯ããããã®èŠçŽ ãå«ã System.Tuple(IList(T1), IList(T2)) ãªããžã§ã¯ããéåæçã«äŒéããŸãã
次ã®åºæ¬çãªäŸã§ã¯ãçµæãBatchedJoinBlock<T1,T2>å€ãããã³Int32ãªããžã§ã¯ãã§ãããšã©ãŒãä¿æããException ãªããžã§ã¯ããäœæããŸãã ãã®äŸã§ã¯ãè€æ°ã®æäœãå®è¡ããçµæã Target1 ããããã£ã«æžã蟌ã¿ããšã©ãŒã Target2 ãªããžã§ã¯ãã® BatchedJoinBlock<T1,T2> ããããã£ã«æžã蟌ã¿ãŸãã æåããæäœãšå€±æããæäœã®æ°ã¯äºåã«äžæã§ããããã IList<T> ãªããžã§ã¯ãã䜿çšãããšãåã¿ãŒã²ãã㯠0 å以äžã®å€ãåãåããŸãã
// For demonstration, create a Func<int, int> that
// returns its argument, or throws ArgumentOutOfRangeException
// if the argument is less than zero.
Func<int, int> DoWork = n =>
{
if (n < 0)
throw new ArgumentOutOfRangeException();
return n;
};
// Create a BatchedJoinBlock<int, Exception> object that holds
// seven elements per batch.
var batchedJoinBlock = new BatchedJoinBlock<int, Exception>(7);
// Post several items to the block.
foreach (int i in new int[] { 5, 6, -7, -22, 13, 55, 0 })
{
try
{
// Post the result of the worker to the
// first target of the block.
batchedJoinBlock.Target1.Post(DoWork(i));
}
catch (ArgumentOutOfRangeException e)
{
// If an error occurred, post the Exception to the
// second target of the block.
batchedJoinBlock.Target2.Post(e);
}
}
// Read the results from the block.
var results = batchedJoinBlock.Receive();
// Print the results to the console.
// Print the results.
foreach (int n in results.Item1)
{
Console.WriteLine(n);
}
// Print failures.
foreach (Exception e in results.Item2)
{
Console.WriteLine(e.Message);
}
/* Output:
5
6
13
55
0
Specified argument was out of the range of valid values.
Specified argument was out of the range of valid values.
*/
' For demonstration, create a Func<int, int> that
' returns its argument, or throws ArgumentOutOfRangeException
' if the argument is less than zero.
Dim DoWork As Func(Of Integer, Integer) = Function(n)
If n < 0 Then
Throw New ArgumentOutOfRangeException()
End If
Return n
End Function
' Create a BatchedJoinBlock<int, Exception> object that holds
' seven elements per batch.
Dim batchedJoinBlock = New BatchedJoinBlock(Of Integer, Exception)(7)
' Post several items to the block.
For Each i As Integer In New Integer() {5, 6, -7, -22, 13, 55, 0}
Try
' Post the result of the worker to the
' first target of the block.
batchedJoinBlock.Target1.Post(DoWork(i))
Catch e As ArgumentOutOfRangeException
' If an error occurred, post the Exception to the
' second target of the block.
batchedJoinBlock.Target2.Post(e)
End Try
Next i
' Read the results from the block.
Dim results = batchedJoinBlock.Receive()
' Print the results to the console.
' Print the results.
For Each n As Integer In results.Item1
Console.WriteLine(n)
Next n
' Print failures.
For Each e As Exception In results.Item2
Console.WriteLine(e.Message)
Next e
' Output:
' 5
' 6
' 13
' 55
' 0
' Specified argument was out of the range of valid values.
' Specified argument was out of the range of valid values.
'
BatchedJoinBlock<T1,T2>ã䜿çšããŠãããã°ã©ã ãããŒã¿ããŒã¹ããèªã¿åãéã«çºçããçµæãšäŸå€ã®äž¡æ¹ããã£ããã£ããå®å šãªäŸã«ã€ããŠã¯ãããã¥ãŒããªã¢ã«: BatchBlock ãš BatchedJoinBlock ã䜿çšããŠå¹çãåäžãããããåç §ããŠãã ããã
ããŒã¿ãã㌠ãããã¯ã®åäœã®æ§æ
ããŒã¿ãã㌠ãããã¯åã®ã³ã³ã¹ãã©ã¯ã¿ãŒã« System.Threading.Tasks.Dataflow.DataflowBlockOptions ãªããžã§ã¯ããæå®ããããšã§ã远å ã®ãªãã·ã§ã³ãæå¹ã«ããããšãã§ããŸãã ãããã®ãªãã·ã§ã³ã¯ãåºã«ãªãã¿ã¹ã¯ã管çããã¹ã±ãžã¥ãŒã©ã䞊ååŠçã®æ¬¡æ°ãªã©ã®åäœãå¶åŸ¡ããŸãã DataflowBlockOptionsã«ã¯ãç¹å®ã®ããŒã¿ãã㌠ãããã¯åã«åºæã®åäœãæå®ããæŽŸçåããããŸãã æ¬¡ã®è¡šã¯ãåããŒã¿ãã㌠ãããã¯ã®çš®é¡ã«é¢é£ä»ããããŠãããªãã·ã§ã³ã®çš®é¡ããŸãšãããã®ã§ãã
次ã®ã»ã¯ã·ã§ã³ã§ã¯ã System.Threading.Tasks.Dataflow.DataflowBlockOptionsã System.Threading.Tasks.Dataflow.ExecutionDataflowBlockOptionsãããã³ System.Threading.Tasks.Dataflow.GroupingDataflowBlockOptions ã¯ã©ã¹ã§äœ¿çšã§ããéèŠãªçš®é¡ã®ããŒã¿ãã㌠ããã㯠ãªãã·ã§ã³ã«é¢ããè¿œå æ å ±ãæäŸããŸãã
ã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ã®æå®
ãã¹ãŠã®å®çŸ©æžã¿ããŒã¿ãã㌠ãããã¯ã§ã¯ãTPL ã¿ã¹ã¯ ã¹ã±ãžã¥ãŒãªã³ã° ã¡ã«ããºã ã䜿çšããŠãããŒã¿ãã¿ãŒã²ããã«äŒéããããœãŒã¹ããããŒã¿ãåä¿¡ãããããŒã¿ã䜿çšå¯èœã«ãªã£ããšãã«ãŠãŒã¶ãŒå®çŸ©ããªã²ãŒããå®è¡ãããªã©ã®ã¢ã¯ãã£ããã£ãå®è¡ããŸãã TaskScheduler ã¯ãã¿ã¹ã¯ãã¹ã¬ããã«ãã¥ãŒã«å ¥ããã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ãè¡šãæœè±¡ã¯ã©ã¹ã§ãã æ¢å®ã®ã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã© ( Default) ã§ã¯ã ThreadPool ã¯ã©ã¹ã䜿çšããŠãã¥ãŒã«ç»é²ããäœæ¥ãå®è¡ããŸãã ããŒã¿ãã㌠ããã㯠ãªããžã§ã¯ããæ§ç¯ãããšãã« TaskScheduler ããããã£ãèšå®ããããšã§ãæ¢å®ã®ã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ããªãŒããŒã©ã€ãã§ããŸãã
åãã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ãè€æ°ã®ããŒã¿ãã㌠ãããã¯ã管çããå Žåããããã®ãããã¯å šäœã«ããªã·ãŒãé©çšã§ããŸãã ããšãã°ãåã ConcurrentExclusiveSchedulerPair ãªããžã§ã¯ãã®æä»ã¹ã±ãžã¥ãŒã©ã察象ãšããããã«è€æ°ã®ããŒã¿ãã㌠ãããã¯ãæ§æãããŠããå Žåããããã®ãããã¯éã§å®è¡ããããã¹ãŠã®äœæ¥ãã·ãªã¢ã«åãããŸãã åæ§ã«ããããã®ãããã¯ãåã ConcurrentExclusiveSchedulerPair ãªããžã§ã¯ãã®åæå®è¡ã¹ã±ãžã¥ãŒã©ãã¿ãŒã²ããã«ããããã«æ§æãããŠããŠããã®ã¹ã±ãžã¥ãŒã©ãæå€§ã³ã³ã«ã¬ã³ã·ãŒ ã¬ãã«ãæã€ããæ§æãããŠããå Žåããããã®ãããã¯ã®ãã¹ãŠã®äœæ¥ã¯ããã®åæå®è¡æäœã®æ°ã«å¶éãããŸãã ConcurrentExclusiveSchedulerPair ã¯ã©ã¹ã䜿çšããŠèªã¿åãæäœã䞊åã§å®è¡ããæžãèŸŒã¿æäœãä»ã®ãã¹ãŠã®æäœã®ã¿ã§å®è¡ããäŸã«ã€ããŠã¯ããæ¹æ³: ããŒã¿ãã㌠ãããã¯ã§ã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ãæå®ããããåç §ããŠãã ããã TPL ã®ã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ã®è©³çްã«ã€ããŠã¯ã TaskScheduler ã¯ã©ã¹ã®ãããã¯ãåç §ããŠãã ããã
䞊ååŠçã®æ¬¡æ°ã®æå®
æ¢å®ã§ã¯ãTPL ããŒã¿ãã㌠ã©ã€ãã©ãªãæäŸãã 3 ã€ã®å®è¡ãããã¯ã®çš®é¡( ActionBlock<TInput>ã TransformBlock<TInput,TOutput>ã TransformManyBlock<TInput,TOutput>)ã¯ãäžåºŠã« 1 ã€ã®ã¡ãã»ãŒãžãåŠçããŸãã ãããã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡ã§ã¯ãåä¿¡ããé åºã§ã¡ãã»ãŒãžãåŠçãããŸãã ãããã®ããŒã¿ãã㌠ãããã¯ã§ã¡ãã»ãŒãžãåæã«åŠçã§ããããã«ããã«ã¯ãããŒã¿ãã㌠ããã㯠ãªããžã§ã¯ããæ§ç¯ãããšãã« ExecutionDataflowBlockOptions.MaxDegreeOfParallelism ããããã£ãèšå®ããŸãã
MaxDegreeOfParallelismã®æ¢å®å€ã¯ 1 ã§ãããŒã¿ãã㌠ãããã¯ãäžåºŠã« 1 ã€ã®ã¡ãã»ãŒãžãåŠçããããšãä¿èšŒããŸãã ãã®ããããã£ã 1 ãã倧ããå€ã«èšå®ãããšãããŒã¿ãã㌠ãããã¯ã§è€æ°ã®ã¡ãã»ãŒãžãåæã«åŠçã§ããŸãã ãã®ããããã£ã DataflowBlockOptions.Unbounded ã«èšå®ãããšãåºã«ãªãã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ã¯ã³ã³ã«ã¬ã³ã·ãŒã®æå€§ã¬ãã«ã管çã§ããŸãã
Von Bedeutung
䞊ååŠçã®æå€§æ¬¡æ°ã 1 ãã倧ããæå®ãããšãè€æ°ã®ã¡ãã»ãŒãžãåæã«åŠçããããããã¡ãã»ãŒãžãåä¿¡ããé åºã§åŠçãããªãå¯èœæ§ããããŸãã ãã ããã¡ãã»ãŒãžããããã¯ããåºåãããé åºã¯ãåä¿¡ãããé åºãšåãã§ãã
MaxDegreeOfParallelism ããããã£ã¯äžŠååŠçã®æå€§é床ã衚ããŠãããããããŒã¿ãã㌠ãããã¯ã¯æå®ããããã䞊ååŠçã®çšåºŠãäœãå ŽåããããŸãã ããŒã¿ãã㌠ãããã¯ã®æ©èœèŠä»¶ãæºããããã«ããŸãã¯äœ¿çšå¯èœãªã·ã¹ãã ãªãœãŒã¹ããªãããã«ã䞊ååŠçã®çšåºŠãäœããªãå¯èœæ§ããããŸãã ããŒã¿ãã㌠ãããã¯ã§ã¯ãæå®ããããã䞊ååŠçãéžæãããããšã¯ãããŸããã
MaxDegreeOfParallelism ããããã£ã®å€ã¯ãåããŒã¿ãã㌠ããã㯠ãªããžã§ã¯ãã«å¯ŸããŠæä»çã§ãã ããšãã°ã4 ã€ã®ããŒã¿ãã㌠ããã㯠ãªããžã§ã¯ãããããã䞊ååŠçã®æå€§æ¬¡æ°ãšã㊠1 ãæå®ããŠããå Žåã4 ã€ã®ããŒã¿ãã㌠ããã㯠ãªããžã§ã¯ããã¹ãŠã䞊åã§å®è¡ãããå¯èœæ§ããããŸãã
é·ãæäœã䞊åã§å®è¡ã§ããããã«äžŠååŠçã®æå€§æ¬¡æ°ãèšå®ããäŸã«ã€ããŠã¯ãã æ¹æ³: ããŒã¿ãã㌠ãããã¯ã§äžŠååŠçã®æ¬¡æ°ãæå®ããããåç §ããŠãã ããã
ã¿ã¹ã¯ãããã®ã¡ãã»ãŒãžæ°ã®æå®
å®çŸ©æžã¿ã®ããŒã¿ãã㌠ãããã¯ã®çš®é¡ã§ã¯ãã¿ã¹ã¯ã䜿çšããŠè€æ°ã®å ¥åèŠçŽ ãåŠçããŸãã ããã«ãããããŒã¿ãåŠçããããã«å¿ èŠãªã¿ã¹ã¯ ãªããžã§ã¯ãã®æ°ãæå°éã«æããããšãã§ããŸããããã«ãããã¢ããªã±ãŒã·ã§ã³ãããå¹ççã«å®è¡ã§ããŸãã ãã ããããŒã¿ãã㌠ãããã¯ã® 1 ã€ã®ã»ããã®ã¿ã¹ã¯ãããŒã¿ãåŠçããŠããå Žåãä»ã®ããŒã¿ãã㌠ãããã¯ã®ã¿ã¹ã¯ã¯ãã¡ãã»ãŒãžããã¥ãŒã«æ ŒçŽããŠåŠçæéãåŸ ã€å¿ èŠãããå ŽåããããŸãã ããŒã¿ãã㌠ã¿ã¹ã¯éã®å ¬å¹³æ§ãé«ããããã«ã MaxMessagesPerTask ããããã£ãèšå®ããŸãã MaxMessagesPerTaskã DataflowBlockOptions.Unbounded (æ¢å®å€) ã«èšå®ãããŠããå ŽåãããŒã¿ãã㌠ãããã¯ã§äœ¿çšãããã¿ã¹ã¯ã¯ã䜿çšå¯èœãªæ°ã®ã¡ãã»ãŒãžãåŠçããŸãã MaxMessagesPerTaskãUnbounded以å€ã®å€ã«èšå®ãããŠããå ŽåãããŒã¿ãã㌠ãããã¯ã¯ãTask ãªããžã§ã¯ãããšã«æå€§ã§ãã®æ°ã®ã¡ãã»ãŒãžãåŠçããŸãã MaxMessagesPerTask ããããã£ãèšå®ãããšãã¿ã¹ã¯éã®å ¬å¹³æ§ãåäžããå¯èœæ§ããããŸãããå¿ èŠä»¥äžã«å€ãã®ã¿ã¹ã¯ãäœæãããããã©ãŒãã³ã¹ãäœäžããå¯èœæ§ããããŸãã
ãã£ã³ã»ã«ã®æå¹å
TPL ã¯ãã¿ã¹ã¯ãå調çã«ãã£ã³ã»ã«ã調æŽã§ããããã«ããã¡ã«ããºã ãæäŸããŸãã ããŒã¿ãã㌠ãããã¯ããã®ãã£ã³ã»ã« ã¡ã«ããºã ã«åå ã§ããããã«ããã«ã¯ã CancellationToken ããããã£ãèšå®ããŸãã ãã® CancellationToken ãªããžã§ã¯ããåãæ¶ãããç¶æ ã«èšå®ãããŠããå Žåããã®ããŒã¯ã³ãç£èŠãããã¹ãŠã®ããŒã¿ãã㌠ãããã¯ã¯çŸåšã®ã¢ã€ãã ã®å®è¡ãçµäºããŸãããåŸç¶ã®é ç®ã®åŠçã¯éå§ããŸããã ãŸãããããã®ããŒã¿ãã㌠ãããã¯ã¯ããããã¡ãŒå ã®ã¡ãã»ãŒãžãã¯ãªã¢ããä»»æã®ãœãŒã¹ ãããã¯ãšã¿ãŒã²ãã ãããã¯ãžã®æ¥ç¶ãè§£æŸããåãæ¶ãããç¶æ ã«é·ç§»ããŸãã åãæ¶ãããç¶æ ã«é·ç§»ããããšã§ã Completion ããããã£ã¯ãåŠçäžã«äŸå€ãçºçããªãéãã Status ããããã£ã Canceled ã«èšå®ããŸãã ãã®å Žåã Status 㯠Faulted ã«èšå®ãããŸãã
Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã§åãæ¶ãã䜿çšããæ¹æ³ã瀺ãäŸã«ã€ããŠã¯ãã æ¹æ³: ããŒã¿ãã㌠ãããã¯ãåãæ¶ãããåç §ããŠãã ããã TPL ã§ã®åãæ¶ãã®è©³çްã«ã€ããŠã¯ãã ã¿ã¹ã¯ã®åãæ¶ãããåç §ããŠãã ããã
æé·äžèŽãšæçäžèŽã®åäœã®æå®
è€æ°ã®ã°ã«ãŒãåããŒã¿ãããŒãããã¯ã®çš®é¡ã¯è²ªæ¬²ã¢ãŒããŸãã¯é貪欲ã¢ãŒãã§åäœã§ããŸãã æ¢å®ã§ã¯ãå®çŸ©æžã¿ã®ããŒã¿ãã㌠ãããã¯ã¯è²ªæ¬²ã¢ãŒãã§åäœããŸãã
JoinBlock<T1,T2>ãªã©ã®çµåãããã¯ã®çš®é¡ã®å Žåã貪欲ã¢ãŒãã§ã¯ãçµåããããã®å¯Ÿå¿ããããŒã¿ããŸã å©çšã§ããªãå Žåã§ãããããã¯ãããã«ããŒã¿ãåãå ¥ããããšãæå³ããŸãã é貪欲ã¢ãŒãã§ã¯ããããã¯ãçµåãå®äºããããã«åã¿ãŒã²ããã«ã¡ãã»ãŒãžãå±ããŸã§ããã¹ãŠã®åä¿¡ã¡ãã»ãŒãžã®åŠçãå»¶æããŸãã å»¶æãããã¡ãã»ãŒãžã®ããããã䜿çšã§ããªããªã£ãå Žåãçµåãããã¯ã¯å»¶æããããã¹ãŠã®ã¡ãã»ãŒãžãè§£æŸããããã»ã¹ãåéããŸãã BatchBlock<T> ã¯ã©ã¹ã®å Žåã貪欲ã¢ãŒããšé貪欲ã¢ãŒãã®åäœã¯äŒŒãŠããŸãããé貪欲ã¢ãŒãã§ã¯ãBatchBlock<T> ãªããžã§ã¯ãã¯ãç°ãªããœãŒã¹ããã®ã¡ãã»ãŒãžãããããå®äºããã®ã«ååãªæ°éãŸããŸã§ããã¹ãŠã®åä¿¡ã¡ãã»ãŒãžã®åŠçãé ãããŸãã
ããŒã¿ãããŒãããã¯ã«å¯ŸããŠé貪欲ã¢ãŒããæå®ããã«ã¯ãGreedy ã False ã«èšå®ããŸãã é貪欲ã¢ãŒãã䜿çšããŠè€æ°ã®çµåãããã¯ãããŒã¿ ãœãŒã¹ãããå¹ççã«å
±æã§ããæ¹æ³ã®äŸã«ã€ããŠã¯ããæ¹æ³: JoinBlock ã䜿çšããŠè€æ°ã®ãœãŒã¹ããããŒã¿ãèªã¿åãããåç
§ããŠãã ããã
ã«ã¹ã¿ã ããŒã¿ãã㌠ãããã¯
TPL ããŒã¿ãã㌠ã©ã€ãã©ãªã«ã¯å€ãã®å®çŸ©æžã¿ãããã¯ã¿ã€ããçšæãããŠããŸãããã«ã¹ã¿ã åäœãå®è¡ãã远å ã®ãããã¯ã¿ã€ããäœæã§ããŸãã ISourceBlock<TOutput>ãŸãã¯ITargetBlock<TInput> ã€ã³ã¿ãŒãã§ã€ã¹ãçŽæ¥å®è£ ããããEncapsulate ã¡ãœããã䜿çšããŠãæ¢åã®ãããã¯åã®åäœãã«ãã»ã«åããè€éãªãããã¯ãæ§ç¯ããŸãã ã«ã¹ã¿ã ããŒã¿ãã㌠ãããã¯æ©èœãå®è£ ããæ¹æ³ã瀺ãäŸã«ã€ããŠã¯ãã ãã¥ãŒããªã¢ã«: ã«ã¹ã¿ã ããŒã¿ãã㌠ãããã¯åã®äœæããåç §ããŠãã ããã
é¢é£ãããã¯
| ã¿ã€ãã« | 説æ |
|---|---|
| æ¹æ³: ããŒã¿ãã㌠ãããã¯ã«ã¡ãã»ãŒãžãæžã蟌ã¿ãããŒã¿ãã㌠ãããã¯ããã¡ãã»ãŒãžãèªã¿åã | BufferBlock<T> ãªããžã§ã¯ãã«ã¡ãã»ãŒãžãæžã蟌ã¿ãã¡ãã»ãŒãžãèªã¿åãæ¹æ³ã瀺ããŸãã |
| æ¹æ³: Producer-Consumer ããŒã¿ãã㌠ãã¿ãŒã³ãå®è£ ãã | ããŒã¿ãã㌠ã¢ãã«ã䜿çšããŠãããã¥ãŒãµãŒ/ã³ã³ã·ã¥ãŒã㌠ãã¿ãŒã³ãå®è£ ããæ¹æ³ã«ã€ããŠèª¬æããŸãããããã¥ãŒãµãŒã¯ããŒã¿ãã㌠ãããã¯ã«ã¡ãã»ãŒãžãéä¿¡ããã³ã³ã·ã¥ãŒããŒã¯ãã®ãããã¯ããã¡ãã»ãŒãžãèªã¿åããŸãã |
| æ¹æ³: ããŒã¿ãã㌠ãããã¯ãããŒã¿ãåä¿¡ãããšãã«ã¢ã¯ã·ã§ã³ãå®è¡ãã | å®è¡ããŒã¿ãã㌠ãããã¯ã®çš®é¡ã ActionBlock<TInput>ã TransformBlock<TInput,TOutput>ãããã³ TransformManyBlock<TInput,TOutput>ã«ããªã²ãŒããæäŸããæ¹æ³ã«ã€ããŠèª¬æããŸãã |
| ãã¥ãŒããªã¢ã«: ããŒã¿ãã㌠ãã€ãã©ã€ã³ã®äœæ | Web ããããã¹ããããŠã³ããŒããããã®ããã¹ãã«å¯ŸããŠæäœãå®è¡ããããŒã¿ãã㌠ãã€ãã©ã€ã³ãäœæããæ¹æ³ã«ã€ããŠèª¬æããŸãã |
| æ¹æ³: ããŒã¿ãã㌠ãããã¯ã®ãªã³ã¯ãè§£é€ãã | LinkTo ã¡ãœããã䜿çšããŠããœãŒã¹ãã¿ãŒã²ããã«ã¡ãã»ãŒãžãæäŸããåŸã§ã¿ãŒã²ãã ãããã¯ã®ãªã³ã¯ãè§£é€ããæ¹æ³ã瀺ããŸãã |
| ãã¥ãŒããªã¢ã«: Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã§ã®ããŒã¿ãããŒã®äœ¿çš | Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã§ç»ååŠçãå®è¡ããããŒã¿ãã㌠ãããã¯ã®ãããã¯ãŒã¯ãäœæããæ¹æ³ã瀺ããŸãã |
| æ¹æ³: ããŒã¿ãã㌠ãããã¯ããã£ã³ã»ã«ãã | Windows ãã©ãŒã ã¢ããªã±ãŒã·ã§ã³ã§ãã£ã³ã»ã«ã䜿çšããæ¹æ³ã瀺ããŸãã |
| æ¹æ³: JoinBlock ã䜿çšããŠè€æ°ã®ãœãŒã¹ããããŒã¿ãèªã¿åã | JoinBlock<T1,T2> ã¯ã©ã¹ã䜿çšããŠãè€æ°ã®ãœãŒã¹ããããŒã¿ãå©çšå¯èœãªå Žåã«æäœãå®è¡ããæ¹æ³ãšãè€æ°ã®çµåãããã¯ãããŒã¿ãœãŒã¹ãããå¹ççã«å ±æã§ããããã«ããããã«ãé貪欲ã¢ãŒãã䜿çšããæ¹æ³ã«ã€ããŠèª¬æããŸãã |
| æ¹æ³: ããŒã¿ãã㌠ãããã¯ã§äžŠååŠçã®æ¬¡æ°ãæå®ãã | MaxDegreeOfParallelism ããããã£ãèšå®ããŠãå®è¡ããŒã¿ãã㌠ãããã¯ã§äžåºŠã«è€æ°ã®ã¡ãã»ãŒãžãåŠçã§ããããã«ããæ¹æ³ã«ã€ããŠèª¬æããŸãã |
| æ¹æ³: ããŒã¿ãã㌠ãããã¯ã§ã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ãæå®ãã | ã¢ããªã±ãŒã·ã§ã³ã§ããŒã¿ãããŒã䜿çšãããšãã«ãç¹å®ã®ã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ãé¢é£ä»ããæ¹æ³ã瀺ããŸãã |
| ãã¥ãŒããªã¢ã«: BatchBlock ãš BatchedJoinBlock ã䜿çšããå¹çã®åäž | BatchBlock<T> ã¯ã©ã¹ã䜿çšããŠããŒã¿ããŒã¹æ¿å ¥æäœã®å¹çãåäžãããæ¹æ³ãšãBatchedJoinBlock<T1,T2> ã¯ã©ã¹ã䜿çšããŠãããã°ã©ã ãããŒã¿ããŒã¹ããèªã¿åãéã«çºçããçµæãšäŸå€ã®äž¡æ¹ããã£ããã£ããæ¹æ³ã«ã€ããŠèª¬æããŸãã |
| ãã¥ãŒããªã¢ã«: ã«ã¹ã¿ã ããŒã¿ãã㌠ãããã¯åã®äœæ | ã«ã¹ã¿ã åäœãå®è£ ããããŒã¿ãã㌠ãããã¯åãäœæãã 2 ã€ã®æ¹æ³ã瀺ããŸãã |
| ã¿ã¹ã¯äžŠåã©ã€ãã©ãª (TPL) | .NET Framework ã¢ããªã±ãŒã·ã§ã³ã§ã®äžŠåããã³åæå®è¡ããã°ã©ãã³ã°ãç°¡ç¥åããã©ã€ãã©ãªã§ãã TPL ã«ã€ããŠèª¬æããŸãã |