2017-06-23 18 views
1

我試圖模擬許多併發用戶(> 2000)來測試Web服務。每個用戶執行在特定的預定義的時間動作,例如:發送許多並行WebRequests

  • 用戶A:9點10分02秒,9點10分03秒,9點10分08秒
  • 用戶B:9點10分:03,9點10分05秒,9時10分07秒
  • 用戶C:9時10分03秒,9時10分09秒,9時十分15秒,9時十分20秒

我現在要在每個時間實時發送網絡請求。我可以容忍最多~2秒的延遲。我已經嘗試沒有成功:

a)總一直在一個列表,排序它通過時間,然後遍歷它:

foreach (DateTime sendTime in times) { 
    while (DateTime.now < sendTime) 
     Thread.Sleep(1); 
    SendRequest(); 
} 

B)爲每個用戶創建一個線程,每個線程檢查對於與上述相同的條件,但睡眠時間較長

兩種方法都有工作,但請求本應發送的時間與實際發送的時間之間的延遲太高。有沒有辦法以更高的精度發送請求?

編輯:建議方法工作得很好。然而,許多請求的延遲仍然非常高。 Apparantly,這樣做的原因是我sendRequest將()方法:

private static async Task SendRequest() 
{ 
    // Log time difference 
    string url = "http://www.request.url/newaction"; 
    WebRequest webRequest = WebRequest.Create(url); 
    try 
    { 
     WebResponse webResponse = await webRequest.GetResponseAsync(); 
    } 
    catch (Exception e) { } 
} 

請注意,我的web服務不返回任何反應,也許這是爲減緩的原因嗎?我可以在不等待回覆的情況下發送請求嗎?

+1

和你的問題? –

+0

我已經添加了更具體的問題 – aseipel

回答

2

我會建議使用計時器對象觸發請求:

// In Form_Load or another init method 
Timer tRequest = new Timer(); 
tRequest.Interval = 500; 
tRequest.Tick += TRequest_Tick; 

private void TRequest_Tick(object sender, EventArgs e) 
{ 
    var sendTimes = times.Where(t => t.AddMilliseconds(-500) < DateTime.Now && t.AddMilliseconds(500) > DateTime.Now); 

    foreach(DateTime sendTime in sendTimes) 
    { 
     SendRequest(); 
    } 
} 
2

,你爲什麼和多線程這樣做呢?線程化需要緩慢的睡眠/喚醒上下文切換。您可以使用定時器/異步調用完成所有操作。

List<DateTime> scheduledTimes = ...; 
List<Task> requests = scheduledTimes 
         .Select(t => t - DateTime.Now) 
         .Select(async delay => 
         { 
          await Task.Delay(delay); 
          SendRequest(); 
         }) 
         .ToList(); 

await Task.WhenAll(requests); 

上述代碼將在一個線程中安排所有請求到SynchronizationContext並運行它們。

簡單。

+0

謝謝,這個作品真的很好。然而,由於我的SendRequest()方法,延遲對於許多請求來說仍然很高。我編輯了我的帖子以獲取更多信息。 – aseipel

+1

@aseipel我認爲其實原因是因爲你正在觸及connectionManager的限制。您也可能達到了http服務器的限制(非服務器Windows上的IIS有意使用連接限制)。 – Aron

+0

如何檢查是否屬於這種情況?我已經增加了我的App.config中的maxconnection屬性,我的服務的IIS連接限制和應用程序池queueLength。 – aseipel