Cannot set delay on getting user followers

Dec 14, 2014 at 10:06 PM
Hello, I have the following function
       private async Task getFriendList()
        {

             .....................................

            var twitterCtx = new TwitterContext(auth);

            Friendship friendship;
            long cursor = -1;
            do
            {
                try
                {
                    friendship =
                        await
                        (from friend in twitterCtx.Friendship
                         where friend.Type == FriendshipType.FriendsList &&
                               friend.ScreenName == textBox2.Text &&
                               friend.Cursor == cursor
                         select friend)
                        .SingleOrDefaultAsync();

                    if (friendship != null &&
                        friendship.Users != null &&
                        friendship.CursorMovement != null)
                    {
                        cursor = friendship.CursorMovement.Next;

                        friendship.Users.ForEach(friend =>
                        {
                            richTextBox1.AppendText(friend.ScreenNameResponse + "\n ");
                            PutTaskDelay(5);
                        });

                    }
                }catch(Exception e){

                    MessageBox.Show("Original error: " + e.Message);
                }
            }while(cursor != 0 && stopbtn == 0);

        }
and the delay function
        async Task PutTaskDelay(int f)
        {
            delay = rnd1.Next(3, 10);
            richTextBox2.AppendText("Delaying: " + delay  + " seconds \n");
            await Task.Delay(delay * 1000);

        }
The problem is that the delay is not working and in the richtextbox the delay is showing

Delaying: 4 seconds
Delaying: 8 seconds
Delaying: 6 seconds
Delaying: 7 seconds
Delaying: 7 seconds
Delaying: 6 seconds
Delaying: 3 seconds
Delaying: 8 seconds
Delaying: 5 seconds
Delaying: 7 seconds
Delaying: 3 seconds
Delaying: 7 seconds
Delaying: 6 seconds
Delaying: 6 seconds
Delaying: 6 seconds
Delaying: 8 seconds
Delaying: 4 seconds
Delaying: 9 seconds

in 1 second, I cannot make that delay and after 300 requests I am receiving code 88 rate limmit exceded and this happen in 2 seconds.
Coordinator
Dec 14, 2014 at 11:43 PM
Hi,

Does it work if you await the call to PutTaskDelay?
    await PutTaskDelay(5);
@JoeMayo
Dec 14, 2014 at 11:46 PM
Image
Dec 15, 2014 at 1:07 AM
Ia not working. How should be the logic of code to make requests to twitter so I can get all 15.000 friends of a user for example? With delay yes? And this delay as I see must be like 300 users / 15 min?
Coordinator
Dec 15, 2014 at 2:32 AM
The error you're seeing is telling you that the lambda the code is in is not async. That's the way async works - the entire call chain has to be async. You could avoid the compiler error by making the lambda async, as in "async friend => ...". However, I don't know why you want to put a delay between text writes to a RichTextBox control, which doesn't seem to contribute directly towards your goal of keeping inside of the Twitter Rate Limit. I would move the await PutTaskDelay out of the ForEach lambda and move it to be the last statement of the try block.

The proper way of handling rate limits will vary by application and your requirements. I see your approach as throttling the process so it doesn't make requests so quickly that it would exceed the rate limit. It also seems somewhat hard-coded, making the assumption that the rate limit will stay that way. I've seen rate limits change over time and they vary depending on the authentication type you're using. There's a Help/RateLimits query that gives you the current rate limit for a given Twitter API endpoint. A more dynamic approach would figure out the rate limit ahead of time and adjust delays according to that. There are many ways to do this, but I just wanted to give you some ideas, rather than thinking there's one right way.

@JoeMayo
Marked as answer by JoeMayo on 12/16/2014 at 5:09 PM
Dec 16, 2014 at 7:19 PM
Yes, you where right I moved the delay after the foreach like this:
            if (friendship != null && friendship.Users != null)
                friendship.Users.ForEach(friend =>
                {
                    richTextBox1.AppendText(friend.ScreenNameResponse + "\n ");
                });

            await PutTaskDelay(5);
and is working. I made the mistake because I didn`t knew that the twitter json returns 20 users, I was thinking one by one lol. Also I modified the query to show me 200 friends:
                        (from friend in twitterCtx.Friendship
                         where friend.Type == FriendshipType.FriendsList &&
                               friend.ScreenName == textBox2.Text &&
                               friend.Cursor == cursor &&
                               friend.Count == 200
                         select friend)