2017-06-23 43 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