Reputation: 728
I'm trying to simulate many concurrent users (>2000) to test a web service. Every user performs actions at a specific pre-defined time, for example:
I now want to send web request in real time at each of those times. I can tolerate a delay of at most ~2 seconds. What I was already trying without success:
a) Aggregate all times in a single list, sort it by time then iterate it:
foreach (DateTime sendTime in times) {
while (DateTime.now < sendTime)
Thread.Sleep(1);
SendRequest();
}
b) Create a thread for each user, with each thread checking for the same condition as above but a longer sleep time
Both approaches kind of work, but the delay between the time that the request was supposed to be sent and the time that it has actually been sent is way too high. Is there any way to send the requests with higher precision?
Edit: The suggests approaches work really well. However, the delay is still extremely high for many requests. Apparantly, the reason for this is my SendRequest() method:
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) { }
}
Note that my web service does not return any response, maybe this is the reason for the slow down? Can I send the request without waiting for the response?
Upvotes: 1
Views: 66
Reputation: 8079
I would suggest to use a timer object to trigger the requests:
// 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();
}
}
Upvotes: 2
Reputation: 15772
Why are you doing this with multiple thread? Threading requires slow sleep/wake context switching. You could just do this all with timers/async calls.
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);
The above code will in one thread schedule all the requests onto the SynchronizationContext
and run them.
Simples.
Upvotes: 2