GC interruptions and TPL

Viewed 500

I have a WCF service. During the service's work, it needs to call two web services. So there's code similar to this:

var task1 = Task.Factory.StartNew(() => _service1.Run(query));
var task2 = Task.Factory.StartNew(() => _service2.Run(query));
Task.WaitAll(new[] { task1 , task2 });

Most of the time this works OK, but occasionally I was seeing spikes in the execution time, where the first task took a few seconds to even begin. Looking at perfmon, I realized this was exactly when GC was happening. Apparently, GC was a higher priority then running my tasks. This is not acceptable, as latency is very important to me, and I'd prefer GC to happen between requests and not in the middle of a request.

I attempted to go about this a different way, and instead of spinning my own tasks, I used WebClient.DownloadStringTask.

return webClient.DownloadStringTask(urlWithParmeters).ContinueWith(t => ProcessResponse(clientQuery, t.Result),
                                                                           TaskContinuationOptions.ExecuteSynchronously);

This didn't help; The GC now runs after the task began, but before the continuation. Again, I guess it figured the system is now idle, so it is a good time to begin GC. Only, I can't afford the latency.

Using TaskCreationOptions.LongRunning, which causes the scheduler to use non thread-pool threads, seems to solve this, but I don't want to create so many new threads - this code is going to run a lot (several times per request).

What is the best way to overcome this issue?

5 Answers
Related