异步函数不会将控制权返回给主线程(linq表达式)

时间:2016-02-27 11:19:31

标签: multithreading

我以为我在.NET中有线程,但是当我添加了LINQ表达式时,它让我有点困惑。

就像我在本讨论的主题中写的那样,我不知道为什么线程不会将控制权返回给我的控制器的主要动作。 我写了一些让我愚蠢的评论,所以让我跳到真实的例子:

/Users/vikasbansal/Desktop/temp/img.jpg

我通过添加“执行器”解决了这个例子,它执行任务列表并对其进行管理。

public class ValuesController : ApiController
    {
        public async Task<List<SomeProduct>> Get()
        {
            var collection = new List<Mother>() {
                new Mother()
                {
                    internalField = new List<Child>()
                    {
                        new Child()
                        {
                            theLastOne = "VAL"
                        },
                        new Child()
                        {
                            theLastOne = "VAL"
                        }
                    }
                }
            };
            var oss =
                from m in collection
                from s in m.internalField
                select Convert(m, s).Result;
            //1-The above code doesnt enter into CONVERT function (I have a breakpoint there)

            return oss.ToList();//2- this list enter into COnvertt
        }

        private async Task<SomeProduct> Convert(Mother ms, Child ss)
        {
            var ossNEW = new SomeProduct();
            await update(ossNEW, ms);
            return ossNEW;
        }

        private async Task update(SomeProduct oss, Mother ms)
        {//3 - Naturally it comes here
            await Task.Run(()=>
            {
                //This task is executed (It is example code, pls do not care, that threads do not have any sense
                oss.copyOfTheLastOne = ms.internalField.First().theLastOne;
                oss.valeFromAnUpdateFunction = "works"; 
            }); //Flow comes here and THIS line does not return control to the main action, why? :)
        }
    }

    public class SomeProduct
    {
        public string copyOfTheLastOne;
        public string valeFromAnUpdateFunction;

    }
    public class Mother
    {
        public List<Child> internalField;

    }

    public class Child
    {
        public string theLastOne;
    }

为了完全理解这个问题,我想知道为什么UPDATE函数不会将控制权返回给主操作,为什么RESULT上的RESULT函数不会强制同步运行程序?

1 个答案:

答案 0 :(得分:1)

  

我想知道为什么UPDATE函数不会将控制权返回给主操作,为什么RESULT上的RESULT函数不会强制同步运行程序?

由于Result的使用,您已经在我的博客上完整地解释了common deadlock problem。使用await代替Result,您的问题就会消失(在您的情况下,因为您有一个集合,您想要await Task.WhenAll):

public async Task<SomeProduct[]> Get()
{
  var collection = new List<Mother>() {
      new Mother()
      {
        internalField = new List<Child>()
        {
          new Child()
          {
            theLastOne = "VAL"
          },
          new Child()
          {
            theLastOne = "VAL"
          }
        }
      }
  };
  var oss =
      from m in collection
      from s in m.internalField
      select Convert(m, s);
  return Task.WhenAll(oss);
}

另外,在您的实现中,您不应该使用Task.Run,特别是在ASP.NET上。在ASP.NET上,Task.Run完全消除了async 的所有好处,并且增加了开销。