2016-11-04 29 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次,沒關係。 –