ãã ããæšæºã®ã¹ã¬ããããŒã«ã䜿çšããããšã¯ãåžžã«å¯èœãŸãã¯åççã§ã¯ãããŸããã ã¹ã¬ããã®æå°æ°ãšæ倧æ°ãæå®ããå¯èœæ§ã«ããããããããã®æ§æã¯ã°ããŒãã«ã§ãããå¿ èŠãªéšåã§ã¯ãªãã¢ããªã±ãŒã·ã§ã³å šäœã«åœ±é¿ããŸãã æ¶è²»è ãµãã©ã€ã€ãŒã®åé¡ã解決ããæ¹æ³ã¯ä»ã«ããããããããŸãã ã¢ããªã±ãŒã·ã§ã³ããžãã¯ããã«ãã¹ã¬ããããã¥ãŒãããã³åæã®åŽé¢ãšæ··åšããŠããå Žåããæ£é¢ãã®ãœãªã¥ãŒã·ã§ã³ã«ãªãå¯èœæ§ããããŸãã ããã¯ãã¯ãŒã¯ãããŒãŸãã¯ã¿ã¹ã¯ã®æ°ãæåã§å¶åŸ¡ããBlockingCollectionã®ã©ãããŒã«ããããšãã§ããŸãã ãŸãã¯ãTPL DataFlowã®ActionBlock <T>ãªã©ã®å®å šãªãœãªã¥ãŒã·ã§ã³ã«åºã¥ãããœãªã¥ãŒã·ã§ã³ã«ããããšãã§ããŸãã
ä»æ¥ã¯ã ActionBlockã¯ã©ã¹ã®å éšæ§é ã調㹠ããã®äœæè ãè¡ã£ãèšèšäžã®æ±ºå®ã«ã€ããŠè°è«ãã䜿çšæã«åé¡ãåé¿ããããã«ããããã¹ãŠãç¥ãå¿ èŠãããçç±ãèŠã€ããŸãã æºåã¯ããïŒ ããã§ã¯è¡ããïŒ
ç§ã®çŸåšã®ãããžã§ã¯ãã§ã¯ããµãã©ã€ã€ãŒãšæ¶è²»è ã®åé¡ã解決ããå¿ èŠãããããã€ãã®ã±ãŒã¹ããããŸãã ãã®1ã€ã¯æ¬¡ã®ããã«ãªããŸããTypeScriptã«éåžžã«ãã䌌ãèšèªçšã®ã«ã¹ã¿ã ããŒãµãŒãšã€ã³ã¿ãŒããªã¿ãŒããããŸãã 詳现ã«æ·±ãå ¥ã蟌ãããšãªããäžé£ã®ãã¡ã€ã«ã解æãããã¹ãŠã®äŸåé¢ä¿ã®ãããããæšç§»çã¯ããŒãžã£ãŒããååŸããå¿ èŠããããšèšããŸãã 次ã«ãå®è¡ã«é©ãããã¬ãŒã³ããŒã·ã§ã³ã«å€æããŠå®è¡ããå¿ èŠããããŸãã
解æããžãã¯ã¯æ¬¡ã®ããã«ãªããŸãã
- Parsimãã¡ã€ã«ã
- ãã®å 容ãåæãããã®äŸåé¢ä¿ãæ¢ããŸãïŒãã¹ãŠã®ãimport * fromãããrequireããããã³åæ§ã®æ§æãåæããŸãïŒã
- äŸåé¢ä¿ãèšç®ããŸãïŒã€ãŸããçŸåšã®ãã¡ã€ã«ãéåžžã®æäœã«å¿ èŠãªãã¡ã€ã«ã®ã»ãããèŠã€ããŸãïŒã
- åä¿¡ããäŸåé¢ä¿ãã¡ã€ã«ã解æçšã®ãªã¹ãã«è¿œå ããŸãã
ããªãç°¡åã§ããã ããã§ãã TPL Dataflowããã³ActionBlock <T>ã¯ã©ã¹ã«åºã¥ãããããã«åçŽåãããå®è£ ã¯æ¬¡ã®ããã«ãªããŸãã
private static Task<ParsedFile> ParseFileAsync(string path) { Console.WriteLine($"Parsing '{path}'. {{0}}", $"Thread Id - {Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(10); return Task.FromResult( new ParsedFile() { FileName = path, Dependencies = GetFileDependencies(path), }); } static void Main(string[] args) { long numberOfProcessedFiles = 0; ActionBlock<string> actionBlock = null; Func<string, Task> processFile = async path => { Interlocked.Increment(ref numberOfProcessedFiles); ParsedFile parsedFile = await ParseFileAsync(path); foreach (var dependency in parsedFile.Dependencies) { Console.WriteLine($"Sending '{dependency}' to the queue... {{0}}", $"Thread Id - {Thread.CurrentThread.ManagedThreadId}"); await actionBlock.SendAsync(dependency); } if (actionBlock.InputCount == 0) { // This is a marker that this is a last file and there // is nothing to process actionBlock.Complete(); } }; actionBlock = new ActionBlock<string>(processFile); actionBlock.SendAsync("FooBar.ts").GetAwaiter().GetResult(); Console.WriteLine("Waiting for an action block to finish..."); actionBlock.Completion.GetAwaiter().GetResult(); Console.WriteLine($"Done. Processed {numberOfProcessedFiles}"); Console.ReadLine(); }
ããã§äœãèµ·ãããèŠãŠã¿ãŸãããã ç°¡åã«ããããã«ããã¹ãŠã®ã³ã¢ããžãã¯ã¯Mainã¡ãœããã«ãããŸãã å€æ°numberOfProcessedFiles㯠ãããžãã¯ãæ£ããããšã確èªããããã«äœ¿çšãããåŠçããããã¡ã€ã«ã®ç·æ°ãå«ãŸããŸãã äž»ãªäœæ¥ã¯processFileããªã²ãŒãã§è¡ãããããªã²ãŒãã¯ActionBlockã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãããŸãã ãã®ããªã²ãŒãã¯ããã³ã³ã·ã¥ãŒãããšããããã€ããŒãã®äž¡æ¹ã®åœ¹å²ãæãããŸããpathåŒæ°ãä»ããŠãã¡ã€ã«ãã¹ãååŸãããã¡ã€ã«ã解æããŠãäŸåé¢ä¿ãèŠã€ãã actionBlock.SendAsyncã¡ãœãããåŒã³åºããŠãã¥ãŒã«æ°ãããã¡ã€ã«ãéä¿¡ããŸãã 次ã«ãåŠçãã¥ãŒå ã®èŠçŽ æ°ã®ãã§ãã¯ããããæ°ããèŠçŽ ããªãå Žåã¯ã actionBlock.CompleteïŒïŒ ïŒ*ïŒãåŒã³åºãããšã§æäœå šäœãå®äºããŸãã 次ã«ã Mainã¡ãœããã¯ActionBlockã€ã³ã¹ã¿ã³ã¹ãäœæããæåã®ãã¡ã€ã«ã®åŠçãéå§ããŠãããã»ã¹å šäœã®çµäºãåŸ ã¡ãŸãã
ParseFileAsyncã¡ãœããã¯ããã¡ã€ã«è§£æããã»ã¹ããšãã¥ã¬ãŒããã次ã®ããªããã£ãããžãã¯ã䜿çšããŠäŸåé¢ä¿ãèšç®ããŸãããã¡ã€ã«ãfoo.tsãã¯ãfo.tsãã«äŸåãããfo.tsãã¯ãf.tsãã«äŸåããŸãã ã€ãŸã åãã¡ã€ã«ã¯ãçãååã®ãã¡ã€ã«ã«äŸåããŠããŸãã ããã¯éçŸå®çãªããžãã¯ã§ããããã¡ã€ã«ã®æšç§»çãªéå ãèšç®ããåºæ¬çãªèãæ¹ã瀺ãããšãã§ããŸãã
ActionBlockã¯ã©ã¹ã¯ã䞊è¡æ§ã管çããŸãã 確ãã« ãããã©ã«ãã®äžŠå床ã¯1ã§ããããšãèæ ®ããå¿ èŠãããããããå€æŽããã«ã¯ã ActionBlockã³ã³ã¹ãã©ã¯ã¿ãŒã§ExecutionDataflowBlockOptionsã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãæž¡ãå¿ èŠããããŸãã MaxDegreeOfParallelismããããã£ã1ãã倧ããå Žåã ActionBlockã¯ç°ãªãã¹ã¬ããïŒå®éã«ã¯ç°ãªãã¿ã¹ã¯ïŒããã³ãŒã«ããã¯ããªã²ãŒããåŒã³åºããŠããã¥ãŒèŠçŽ ã䞊ååŠçããŸãã
æçš¿ãš SendAsyncïŒäœããã€äœ¿çšããã
äŸçµŠè ãšæ¶è²»è ã®åé¡ãå°ãªããšãäžåºŠç¬ç«ããŠè§£æ±ºããããšãã人ã¯èª°ã§ãåé¡ã«çŽé¢ããŸãããå ¥åããŒã¿ã¹ããªãŒã ãåŠçäžã®æ¶è²»è ã®èœåãè¶ ããå Žåã¯ã©ãããã°ããã§ãããã å ¥åã¹ããªãŒã ããçµããæ¹æ³ã¯ïŒ ãã¹ãŠã®å ¥åèŠçŽ ãã¡ã¢ãªã«ä¿åããã ãã§ããïŒ äŸå€ãæããŸããïŒ ã¢ã€ãã ã®è¿œå ã¡ãœããã§falseãè¿ããŸããïŒ åŸªç°ãããã¡ã䜿çšããŠå€ãèŠçŽ ãç Žæ£ããŸããïŒ ãŸãã¯ããã¥ãŒã«å Žæã衚瀺ããããŸã§ãã®ã¡ãœããã®å®è¡ããããã¯ããŸããïŒ
ãã®åé¡ã解決ããããã«ã ActionBlockã®äœæè ã¯ã次ã®äžè¬çã«åãå ¥ããããŠããã¢ãããŒãã䜿çšããããšã«ããŸããã
- ã¯ã©ã€ã¢ã³ãã¯ã ActionBlockãªããžã§ã¯ããäœæãããšãã«ãã¥ãŒã®ãµã€ãºãæå®ã§ããŸãã
- ãã¥ãŒããã£ã±ãã®å Žåã Postã¡ãœããã¯falseãè¿ãã SendAsyncæ¡åŒµã¡ãœããã¯ããã¥ãŒã«ç©ºãé åããããšãã«å®äºããã¿ã¹ã¯ãè¿ããŸãã
åã®äŸã§ã¯ããã¥ãŒã®ãµã€ãºãèšå®ããŸããã§ããã ãŸããããã¯ãæ°ããèŠçŽ ãåŠçããããããéãè¿œå ããããšãã¢ããªã±ãŒã·ã§ã³ãé ããæ©ããOutOfMemoryExceptionã§ã¯ã©ãã·ã¥ããããšãæå³ããŸãã ãããããã®ç¶æ³ãä¿®æ£ããŠã¿ãŸãããã ãããŠããã¥ãŒãéåžžã«å°ããªãµã€ãºãããšãã°1èŠçŽ ã«èšå®ããŸãã
actionBlock = new ActionBlock<string>(processFile, new ExecutionDataflowBlockOptions() {BoundedCapacity = 1});
ããŠããã®ã³ãŒããå®è¡ãããšã...ãããããã¯ãçºçããŸãïŒ
ãããããã¯
ãã¶ã€ã³ã®èŠ³ç¹ããæ¶è²»è ãšäŸçµŠè ã®åé¡ãèããŠã¿ãŸãããã èŠçŽ ãåŠçããããã®ã³ãŒã«ããã¯ã¡ãœãããåãå ¥ããç¬èªã®ãã¥ãŒãäœæããŸãã èŠçŽ æ°ã®å¶éããµããŒããããã©ããã決å®ããå¿ èŠããããŸãã ãå¶éãããããã¥ãŒãå¿ èŠãªå ŽåãããããActionBlockã¯ã©ã¹ã®èšèšã«éåžžã«ãã䌌ãèšèšã«ãªããŸãããã¥ãŒããã£ã±ãã®å Žåã«falseãè¿ãèŠçŽ ãè¿œå ããåæã¡ãœãããšãã¿ã¹ã¯ãè¿ãéåæã¡ãœãããè¿œå ããŸãã ãã¥ãŒããã£ã±ãã®å Žåãã¯ã©ã¹ã®ã¯ã©ã€ã¢ã³ãã¯äœããã¹ããã決å®ããæ©äŒããããŸããèŠçŽ ãè¿œå ããåæããŒãžã§ã³ãåŒã³åºãããšã§ç¬èªã«ããªãŒããŒãããŒããåŠçããããéåæããŒãžã§ã³ã䜿çšããŠãã¥ãŒå ã®ç©ºãã¹ããŒã¹ã®åºçŸããåŸ æ©ãããŸãã
次ã«ãã³ãŒã«ããã¯ã¡ãœããããã€åŒã³åºããã決å®ããå¿ èŠããããŸãã ãã®çµæã次ã®ããžãã¯ã«å°éã§ããŸãããã¥ãŒã空ã§ãªãå Žåãæåã®èŠçŽ ãååŸãããã³ãŒã«ããã¯ã¡ãœãããåŒã³åºãããåŠçãå®äºãããšäºæ³ããããã®åŸèŠçŽ ããã¥ãŒããåé€ãããŸãã ïŒå®éã®å®è£ ã¯ãããããçš®é¡ã®äººçš®ãèæ ®ã«å ¥ããå¿ èŠããããããèŠãããããã¯ããã«è€éã«ãªããŸãïŒã ãã¥ãŒã¯ãã³ãŒã«ããã¯ã¡ãœãããåŒã³åºãåã«ã¢ã€ãã ãåé€ããããšã決å®ã§ããŸãããããã«ãããããã«ãããã¯ãããããã¯ãåãåãå¯èœæ§ã«åœ±é¿ããŸããã
ã·ã³ãã«ã§ãšã¬ã¬ã³ããªãã¶ã€ã³ãæãã€ããŸããããç°¡åã«åé¡ã«ã€ãªããå¯èœæ§ããããŸãã ãã¥ãŒããã£ã±ãã§ãèŠçŽ ã®1ã€ãåŠçããããã«ã³ãŒã«ããã¯ãåŒã³åºãããŠãããšããŸãã ãããã管çãã¥ãŒããã°ãããè¿ãã代ããã«ããã³ãã©ãŒãawait SendAsyncãåŒã³åºããŠå¥ã®èŠçŽ ãè¿œå ããããšãããšã©ããªããŸããã
ã³ãŒã«ããã¯ã¡ãœããããŸã å®äºããŠããªãããããã¥ãŒããã£ã±ãã§æ°ããã¢ã€ãã ãåãå ¥ããããšãã§ããŸããã ãããããã®ã¡ãœãããã SendAsyncã®åŸ æ©ãå®äºããã®ãåŸ ã£ãŠ ã¹ã¿ãã¯ã ãå Žæããã¥ãŒã€ã³ã°ããããŸã§ç§»åã§ããŸããã§ããã å€å žçãªãããããã¯ïŒ
ã³ãŒã«ããã¯ã¡ãœããã*å®äºããåŸã ActionBlockããã¥ãŒããã¢ã€ãã ãåé€ããããããããããã¯ãçºçããŸãã ããããå¥ã®ã·ããªãªãèŠãŠã¿ãŸãããïŒ ActionBlockãã³ãŒã«ããã¯ã¡ãœãããåŒã³åºãåã«*èŠçŽ ãåé€ãããšã©ããªããŸããïŒ å®éãäœãå€ãããŸããã ãããããã¯ã¯åŒãç¶ãå¯èœã§ãã
ãã¥ãŒãµã€ãºã1ã§ã䞊å床ã2ã§ãããšæ³åããŠãã ããã
- ã¹ã¬ããT1ã¯ãã¢ã€ãã ããã¥ãŒã«è¿œå ããŸãã ActionBlock㯠ããã¥ãŒããèŠçŽ ãåé€ãïŒãã¥ãŒå ã®èŠçŽ ã®æ°ã0ã«æžãããŸãïŒãã³ãŒã«ããã¯ã¡ãœãããåŒã³åºããŸãã
- ã¹ã¬ããT2ã¯ãã¢ã€ãã ããã¥ãŒã«è¿œå ããŸãã ActionBlock㯠ããã¥ãŒããèŠçŽ ãåé€ãïŒãã¥ãŒå ã®èŠçŽ ã®æ°ã0ã«æžãããŸãïŒãã³ãŒã«ããã¯ã¡ãœãããåŒã³åºããŸãã
- ã¹ã¬ããT1ã¯ãã¢ã€ãã ããã¥ãŒã«è¿œå ããŸãã 䞊ååŠçã®ã¬ãã«ã¯2ã§ããããã§ã«2ã€ã®ãã³ãã©ãŒããããããActionBlockã¯æ°ããèŠçŽ ã®ãã³ãã©ãŒãåŒã³åºãããšãã§ããŸããã ãã¥ãŒããã£ã±ãã§ãã
- åŠçäžã®æåã®ãã³ãã©ãŒã¯ããã¥ãŒã«æ°ããèŠçŽ ãè¿œå ããããšããŸããããã¥ãŒããã£ã±ãã§ãããããã await SendAsync ãã®åŒã³åºãã«åºå·ããŸãã
- åŠçäžã®2çªç®ã®ãã³ãã©ãŒã¯ãæ°ããèŠçŽ ããã¥ãŒã«è¿œå ããããšããŸããããã¥ãŒããã£ã±ãã§ããããã ' await SendAsync 'ã®åŒã³åºãã«åºå·ããŸãã
åŠçåã«ãã¥ãŒããã¢ã€ãã ãåé€ããŠãå¹æããªãããšãããããŸãã ããã«ããããããã¯ã®ç¢ºçãå€§å¹ ã«äœäžãããããããã¯åé¡ãæªåãããã ãã§ãïŒäžŠå床ãNã«çããå Žåããã¹ãŠã®Nã³ãŒã«ããã¯ã¡ãœãããæ°ããèŠçŽ ãåæã«ãã¥ãŒã«è¿œå ããããšããå¿ èŠããããŸãïŒã
å¥ã®æ¬ ç¹ã¯ããã»ã©æçœã§ã¯ãããŸããã ActionBlockã¯ãŸã æ±çšãœãªã¥ãŒã·ã§ã³ã§ã¯ãããŸããã ãã®ã¯ã©ã¹ã¯ITargetSourceã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããè€éãªããŒã¿ãããŒã¹ã¯ãªããã®èŠçŽ ãåŠçããããã«äœ¿çšã§ããŸãã ããšãã°ãèŠçŽ ã®äžŠååŠçã®ããã®ããã€ãã®ãã¿ãŒã²ããããããã¯ãæã€BufferBlockããããŸãã çŸåšã®å®è£ ã§ã¯ããã©ã³ã·ã³ã°ãã³ãã©ãŒã¯ç°¡åãªæ¹æ³ã§å®è£ ãããŠããŸãã ã¬ã·ãŒããŒïŒãã®å Žåã¯ActionBlock ïŒããã£ã±ãã«ãªããšãå ¥åçšã®æ°ããèŠçŽ ã®åãå ¥ããåæ¢ããŸãã ããã«ããããã§ãŒã³å ã®ä»ã®ãããã¯ã代ããã«èŠçŽ ãåŠçã§ããŸãã
èŠçŽ ãåŠçãããåŸã«ã®ã¿åé€ãããå ŽåãActionBlockã¯è²ªæ¬²ã«ãªããçŸåšåŠçã§ãããããå€ãã®èŠçŽ ãåãå ¥ããŸãã ãã®å Žåãåãããã¯ã®å¶é容éã¯ãBoundedCapaciyã+ãMaxDegreeOfParallelismãã«çãããªããŸãã
ãããããã¯ã®åé¡ã解決ããæ¹æ³ã¯ïŒ
ç§ã¯äœãæããŠããªãã åæã«ãã¥ãŒå ã®èŠçŽ ã®æ°ãå¶éããå¿ èŠããããã³ãŒã«ããã¯ã¡ãœãããæ°ããèŠçŽ ãè¿œå ã§ããå Žå ã ActionBlockãæŸæ£ããå¿ èŠããããŸã ã å¥ã®æ¹æ³ãšããŠã BlockingCollectionãšã¯ãŒã¯ãããŒã®æ°ã®ãæåãå¶åŸ¡ã«åºã¥ããœãªã¥ãŒã·ã§ã³ããããŸããããšãã°ãã¿ã¹ã¯ããŒã«ãŸãã¯Parallel.Invokeã䜿çšããŸãã
䞊å床
TPLã®ããªããã£ããšã¯ç°ãªããTPL Dataflowã®ãã¹ãŠã®ãããã¯ã¯ããã©ã«ãã§ã·ã³ã°ã«ã¹ã¬ããã§ãã ã€ãŸã ActionBlock ã TransformerBlockãªã©ã¯ãã³ãŒã«ããã¯ã¡ãœããã1ã€ãã€åŒã³åºããŸãã TPL Dataflowã®äœæè ã¯ãããã©ãŒãã³ã¹ã®åäžãããã·ã³ãã«ããéèŠã ãšèããŸããã ããŒã¿ãããŒã°ã©ãã«ã€ããŠèããã®ã¯éåžžã«é£ããããã¹ãŠã®ãããã¯ã§ããŒã¿ã䞊ååŠçãããšããã®ããã»ã¹ã¯ããã«é£ãããªããŸãã
䞊å床ãå€æŽããã«ã¯ããããã¯ã¯ExecutionDataflowBlockOptionsãæž¡ãã MaxDegreeOfParallelismããããã£ã 1ãã倧ããå€ã«èšå®ããå¿ èŠããããŸããã¡ãªã¿ã«ããã®ããããã£ã-1ã«èšå®ãããŠããå Žåããã¹ãŠã®çä¿¡èŠçŽ ã¯æ°ããã¿ã¹ã¯ã«ãã£ãŠåŠçããã䞊ååŠçã¯äœ¿çšãããã¿ã¹ã¯ã¹ã±ãžã¥ãŒã©ïŒ TaskSchedulerãªããžã§ã¯ãïŒã®æ©èœã«ãã£ãŠã®ã¿å¶éãããŸãExecutionDataflowBlockOptionsãä»ããŠæž¡ãããšãã§ããŸãã
ãããã«
䜿ããããã³ã³ããŒãã³ãã®èšèšã¯å°é£ã§ãã 䞊è¡æ§ã®åé¡ã解決ãã䜿ããããã³ã³ããŒãã³ãã®èšèšã¯ãäºéã«é£ãããªããŸãã ãããã®ã³ã³ããŒãã³ããæ£ãã䜿çšããã«ã¯ããããã®å®è£ æ¹æ³ãšãéçºè ã念é ã«çœ®ããŠããå¶éãç¥ãå¿ èŠããããŸãã
ActionBlock <T>ã¯ã©ã¹ã¯çŽ æŽããããã®ã§ããµãã©ã€ã€ãšã³ã³ã·ã¥ãŒãã®ãã¿ãŒã³ã®å®è£ ãå€§å¹ ã«ç°¡çŽ åããŸãã ãã ãããã®å Žåã§ãã䞊å床ããªãŒããŒãããŒã®å Žåã®ãããã¯ã®åäœãªã©ãTPL Dataflowã®ããã€ãã®åŽé¢ã«ã€ããŠç¥ã£ãŠããå¿ èŠããããŸãã
-ïŒ*ïŒãã®äŸã¯ã¹ã¬ããã»ãŒãã§ã¯ãªããããå®å šãªå®è£ ã§ã¯actionBlock.InputCountã䜿çšããªãã§ãã ãã ã åé¡ããããŸããïŒ
ïŒ**ïŒ Postã¡ãœããã¯ã2ã€ã®ã±ãŒã¹ã®ããããã§falseãè¿ããŸãããã¥ãŒããã£ã±ãã§ãããããã§ã«å®äºããŠããŸãïŒ Completeã¡ãœãããåŒã³åºãããŸãïŒã ãããã®2ã€ã®ã±ãŒã¹ãåºå¥ã§ããªãããããã®åŽé¢ã¯ãã®æ¹æ³ã®äœ¿çšãè€éã«ããå¯èœæ§ããããŸãã äžæ¹ã SendAsyncã¡ãœããã®åäœã¯å€å°ç°ãªããŸãããã®ã¡ãœããã¯ããã¥ãŒããã£ã±ãã®ãšãã«æªå®äºç¶æ ã«ãªãTask <bool>ãªããžã§ã¯ããè¿ããŸããããã¥ãŒãæ¢ã«å®äºããŠãããæ°ããèŠçŽ ãåãå ¥ããããšãã§ããªãå Žåã task.Resultã¯falseã«ãªããŸã ã