Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It would appear that your problem happens when a request is queued up when another one is already waiting. Here's my take on your pseudo code:</p> <pre><code>using System; using System.Threading; using System.Threading.Tasks; namespace ThrottledAsync { class Program { static void Main(string[] args) { // Queue up multiple user actions // within a short interval. for (var i = 0; i &lt; 10; i++) { OnUserAction(); Thread.Sleep(10); } Console.ReadLine(); } private static int UserActionID; private static DateTime previousWaitStartTime; public static async void OnUserAction() { // Keep track of the operation ID. var userActionID = Interlocked.Increment(ref UserActionID); // Pseudo-code implementation. var timeUntilPreviousCallWillBeOrWasMade = 1000 - (int)(DateTime.Now.Subtract(previousWaitStartTime).TotalMilliseconds); Console.WriteLine( "{0:HH:mm:ss.ffff} - User action {1}: timeUntilPreviousCallWillBeOrWasMade = {2}.", DateTime.Now, userActionID, timeUntilPreviousCallWillBeOrWasMade); var timeToWaitBeforeThisCallShouldBeMade = Math.Max(0, timeUntilPreviousCallWillBeOrWasMade + 1000); Console.WriteLine( "{0:HH:mm:ss.ffff} - User action {1}: timeToWaitBeforeThisCallShouldBeMade = {2}.", DateTime.Now, userActionID, timeToWaitBeforeThisCallShouldBeMade); previousWaitStartTime = DateTime.Now; await Task.Delay(timeToWaitBeforeThisCallShouldBeMade); await MakeCallToWebService(userActionID); } private static async Task MakeCallToWebService(int userActionID) { // Simulate network delay. await Task.Delay(new Random().Next(5, 10)); Console.WriteLine("{0:HH:mm:ss.ffff} - User action {1}: web service call.", DateTime.Now, userActionID); } } } </code></pre> <p>And the output:</p> <pre><code>19:10:11.1366 - User action 1: timeUntilPreviousCallWillBeOrWasMade = -2147482648. 19:10:11.1416 - User action 1: timeToWaitBeforeThisCallShouldBeMade = 0. 19:10:11.1536 - User action 2: timeUntilPreviousCallWillBeOrWasMade = 988. 19:10:11.1536 - User action 2: timeToWaitBeforeThisCallShouldBeMade = 1988. 19:10:11.1586 - User action 1: web service call. 19:10:11.1646 - User action 3: timeUntilPreviousCallWillBeOrWasMade = 990. 19:10:11.1646 - User action 3: timeToWaitBeforeThisCallShouldBeMade = 1990. 19:10:11.1756 - User action 4: timeUntilPreviousCallWillBeOrWasMade = 990. 19:10:11.1756 - User action 4: timeToWaitBeforeThisCallShouldBeMade = 1990. 19:10:11.1866 - User action 5: timeUntilPreviousCallWillBeOrWasMade = 990. 19:10:11.1866 - User action 5: timeToWaitBeforeThisCallShouldBeMade = 1990. 19:10:11.1976 - User action 6: timeUntilPreviousCallWillBeOrWasMade = 990. 19:10:11.1986 - User action 6: timeToWaitBeforeThisCallShouldBeMade = 1990. 19:10:11.2086 - User action 7: timeUntilPreviousCallWillBeOrWasMade = 990. 19:10:11.2086 - User action 7: timeToWaitBeforeThisCallShouldBeMade = 1990. 19:10:11.2186 - User action 8: timeUntilPreviousCallWillBeOrWasMade = 990. 19:10:11.2196 - User action 8: timeToWaitBeforeThisCallShouldBeMade = 1990. 19:10:11.2296 - User action 9: timeUntilPreviousCallWillBeOrWasMade = 990. 19:10:11.2296 - User action 9: timeToWaitBeforeThisCallShouldBeMade = 1990. 19:10:11.2406 - User action 10: timeUntilPreviousCallWillBeOrWasMade = 990. 19:10:11.2406 - User action 10: timeToWaitBeforeThisCallShouldBeMade = 1990. 19:10:13.1567 - User action 2: web service call. 19:10:13.1717 - User action 3: web service call. 19:10:13.1877 - User action 5: web service call. 19:10:13.1877 - User action 4: web service call. 19:10:13.2107 - User action 6: web service call. 19:10:13.2187 - User action 7: web service call. 19:10:13.2187 - User action 8: web service call. 19:10:13.2357 - User action 9: web service call. 19:10:13.2537 - User action 10: web service call. </code></pre> <p>You should really be using the right tool for the job. How about a <code>SemaphoreSlim</code>?</p> <pre><code>using System; using System.Threading; using System.Threading.Tasks; namespace ThrottledAsync { class Program { static void Main(string[] args) { // Queue up simultaneous calls. MakeThrottledCall(); MakeThrottledCall(); MakeThrottledCall(); MakeThrottledCall(); Console.ReadLine(); } // Used to throttle our web service calls. // Max degree of parallelism: 1. private static readonly SemaphoreSlim WebServiceMutex = new SemaphoreSlim(1, 1); private static async void MakeThrottledCall() { // Wait for the previous call // (and delay task) to complete. await WebServiceMutex.WaitAsync(); try { await MakeCallToWebService(); // Report the completion of your web service call if necessary. // Delay for a bit before releasing the semaphore. await Task.Delay(1000); } finally { // Allow the next web service call to go through. WebServiceMutex.Release(); } } private static async Task MakeCallToWebService() { // Simulate network delay. await Task.Delay(new Random().Next(5, 10)); Console.WriteLine("WebServiceCall: {0:HH:mm:ss.ffff}", DateTime.Now); } } } </code></pre> <p>EDIT: <code>MakeThrottledCall</code> no longer returns <code>Task</code> as per svick's comment.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload