2016-11-04 30 views
3

我创建一个asp.net的WebAPI测试应用程序,这是我的测试代码:为什么这么慢,.NET任务巢子任务

当我使用result = index.ToString() + this.getresult().Result;,响应时间为2s。如果我使用Thread.Sleep(100); result = index.ToString();,它只需要200ms。

public class HomeController : Controller 
{ 
    public string Test() 
    { 
     var listName = new List<int>(); 

     for (int i = 0; i < 100; i++) 
     { 
      listName.Add(i); 
     } 

     var response = Task.WhenAll(listName.Select(sendrequest)).Result; 

     return string.Join(",", response); 
    } 

    public async Task<string> sendrequest(int index) 
    { 
     return await Task.Factory.StartNew(() => 
     { 
      string result = string.Empty; 

      try 
      { 
       Thread.Sleep(100); result = index.ToString(); 
       //result = index.ToString() + this.getresult().Result; 
      } 
      catch (Exception ex) 
      { 
       System.IO.File.AppendAllText("D:\\WebService\\FelixTest\\log.txt",ex.ToString()); 
      } 

      return result; 

     }).ConfigureAwait(false); 
    } 

    public async Task<string> getresult() 
    { 
     await Task.Delay(100); 

     return "OK"; 
    } 
} 
+1

可能是因为您在getresult方法中使用延迟? – ThunD3eR

+0

你是如何测量时间的?在你的'延迟'只有100(毫秒,默认情况下),所以它不应该需要2秒...但它可能取决于你如何测量运行应用程序所需的时间。 – Shaamaan

回答

2

我认为你患有ThreadPool线程挨饿。问题就出在该行已被注释掉

//result = index.ToString() + this.getresult().Result; 

通过访问Task.Result属性,是造成从getresult()方法返回的Task一个Wait。 Wait操作会阻止当前线程执行,这意味着下一个Task必须安排在另一个线程上等等。当你启动100个任务时,所有这些任务都会阻塞,ThreadPool将尝试启动新的托管线程以满足需求,这是一个耗时的过程。

我会重新组织您的代码,以便除了顶级方法Test之外,所有内容都是异步的。在这个例子中,我不确定为什么你需要Task.Factory.StartNew(),因为任务已经运行(至少部分)并行,这是因为它们使用了异步等待模式。也许你现实生活中的例子需要在后台线程上安排任务?如果您不需要使用Factory.StartNew()我建议重写sendrequest这样的: -

public async Task<string> sendrequest(int index) 
{ 
    string result = string.Empty; 
    try 
    { 
     result = index.ToString() + await this.getresult(); 
    } 
    catch (Exception ex) 
    { 
     System.IO.File.AppendAllText("D:\\WebService\\FelixTest\\log.txt",ex.ToString()); 
    } 

    return result; 
} 

如果确实需要使用Factory.StartNew()你仍然可以实现同样的事情,但你传递给StartNew委托应标记为async

+0

谢谢,它看起来像真相。 –

1

根据你的描述,差值为1800毫秒。 getresult延迟了100毫秒。如果我们减去它,差异是1700毫秒。与"OK"字符串连接不解释。因此,你可能使用一个循环,并在getresult 100毫秒的延迟加起来等待。

+0

嗨,我更新了问题。添加thread.sleep(100),现在响应时间是200ms。 –

+0

如果你调试你的代码,它会输入多少次getresult? –

+0

100次,没关系。 –