Task.Run 不运行方法?

Posted

技术标签:

【中文标题】Task.Run 不运行方法?【英文标题】:Task.Run does not run the methods? 【发布时间】:2020-04-18 13:15:24 【问题描述】:

我在 ASP.NET 应用程序中有一个奇怪的错误。我有 2 种方法可以计算插入 CSV 文件中的贷款利息和本金。奇怪的是,如果我在第一次启动应用程序时将计算包装在 Task.Run() 中,则计算未完成,并且我在 CSV 中收到值 0。第二次运行计算时(当应用程序仍在运行时),它们被正确计算并插入到 CSV 文件中。我禁用了 Task.Run() 并运行了计算,并且不再遇到此错误。此外,当计算在 Task.Run() 中运行时,我尝试调试应用程序,如果我调试并运行代码,则计算正确完成并插入 CSV 文件(即使是我第一次运行应用)。我相信这是一个线程问题,但我不确定问题是什么。 这些是进行计算的两种方法:

 public  static double CalculateInterestRate(IBankingModel bm)
            
                Task.Run(() =>
                
                    switch (bm.IsVariable)
                    
                        case true:
                            InterestRate = (EURIBOR + FixedRateE) * bm.LoanAmount;
                            break;
                        case false:
                            InterestRate = bm.InterestPercent * bm.LoanAmount;
                            break;
                    
                );
                return InterestRate;
            

public static double CalculatePrincipal(IBankingModel bm)
 
            Task.Run(() =>
            
                Principal = bm.LoanAmount - InterestRate;
            );           

            return Principal;
  

这是插入数据的方法:

[AllowAnonymous]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Insert(BankingModel bm)
        
            using (StreamWriter a = new StreamWriter(_path.MapPath, true))
            

                a.WriteLine($"bm.PIN,bm.Name,bm.Surname,bm.LoanAmount," +
                    $"bm.InterestPercent,bm.IsVariable,Matrix.CalculateInterestRate(bm).ToString(),Matrix.CalculatePrincipal(bm).ToString()");

            
            return RedirectToAction("Main");
        

【问题讨论】:

您能解释一下为什么您使用Task.Run吗?没有它会更好用 我在想Task.Run(),因为计算是在处理器上完成的,它会使用线程池中的一个新线程,它会更快地运行计算,提高速度应用程序。如果我错了,请纠正我。 这些是非常简单的计算。切换到另一个核心可能需要比您节省的时间更多的时间。它可能会导致计算发生在之后您返回之前的值 这些不是 CPU 密集型计算,不会从在单独的线程上运行中受益 【参考方案1】:

通过调用Task.Run(() =>...,您只是将该函数指定为在新线程中异步执行。而且您不会等待它完成。并且return 立即执行,无需等待任务完成。这就是结果为 0 的原因。您必须使用 async/await 等待该任务完成:

public static async Task<double> CalculatePrincipal(IBankingModel bm)
 
      await Task.Run(() =>
      
           //... some time-consuming operation
           Principal = bm.LoanAmount - InterestRate;
      );       

      return Principal;    
  

在这种情况下,您还必须在调用CalculatePrincipal 时使用await

var result = await CalculatePrincipal(bm);

但是,如果该计算不是耗时的操作,则无需使用Task。只需返回差值:

public static double CalculatePrincipal(IBankingModel bm)

    return  bm.LoanAmount - InterestRate;
 

【讨论】:

好的,我理解解释,但似乎只有在我第一次在应用程序中运行计算时才立即执行返回,之后计算正确返回。你有什么知道为什么会这样? @WorkoutChannel 总是会立即执行。可能是您看到了结果,因为您在 Task 中设置了 Principal

以上是关于Task.Run 不运行方法?的主要内容,如果未能解决你的问题,请参考以下文章

C# Task.Run()运行“含参数和返回值的方法”的用法

使用异步方法等待 Task.Run 不会在正确的线程上引发异常

使用 Task.Run() 时如何避免 OutOfMemoryException? [复制]

Task.Run 和Task.Factory.StartNew 区别

Task.Run()方法总结

Task.Run 中的异步 lambda 与常规 lambda [重复]