Action<TwitterAsyncResponse<User>> callback

Feb 23, 2011 at 8:05 PM

Hi !

I've searched a little bit on google, can't understand how to use async functions that resides in the API.

Can someone take a minute and give me an example ?

Let's say I want to call UpdateAccountImage asynchronously...

It's the concept I'm having a hard time to understand, plus Lambda is new to me...

public virtual User UpdateAccountImage(string imageFilePath, Action<TwitterAsyncResponse<User>> callback)

...

authContext.UpdateAccountImage("myimagepath.jpg", theFamousCallBack);

I'm in C#.

Thanks.

Coordinator
Feb 23, 2011 at 8:52 PM

Hi,

In normal coding, you call a method and wait on the return value.  Waiting like this is referred to as synchronous.  However, sometimes you call a method that takes a while to complete.  i.e. writing to a file, performing a calculation, or waiting on an image update to Twitter. In the meantime, you don't want your UI to lock up; rather, it would be more comfortable for the user to continue doing what they want or show them a progress bar and then notify them when the operation is complete.  This pattern of starting work, returning to the user immediately, and then notifying the user when the operation is complete falls in the the category of asynchronous programming.  A good analogy might be a toaster; you grab bread, stick it in the toaster and push the lever down, which is synchronous.  However, while the toast cooks (or burns in my case), you pour coffee, grab some jam, and prepare the table.  Eventually, the toaster will pop (or set off the fire alarm), at which time you'll resume synchronous operations and prepare the toast and eat (or throw the burnt crumbs away and make a bowl of cereal).  The preparation of the toast is like setting up a method call.  The toast cooking is like a method that has been called and control returning to the user to resume what they want to do.  The toast popping is like the asynchronous callback, giving you the chance to look at and handle data (or manage an error handling routine).

Here's some code from the downloadable LINQ to Twitter souce code solution.  You can find it in the Silverlight Demos.  A short modification would look like this:

            m_twitterCtx.UpdateStatus("Test Tweet",
                updateResp => Console.Writeline("User: " + updateResp.State.User.Identifier.ScreenName));

This uses a lambda, which conforms to an Action delegate signature.  Lambdas can be used in place of delegates as long as they have the same signature.  In the code above, updateResp, is the parameter that is assigned by LINQ to Twitter when the UpdateStatus method invokes the callback (when it gets the results back from Twitter).  The Lambda is just a method without a name.  If you wanted, you could have written a named method and passed the method name as the 2nd parameter of UpdateStatus, which would have invoked the code in your method.  However, the Lambda gave me the ability to put the logic for managing the callback in the same place as the original call, rather than having more moving parts than I need.  The Console.Writeline is the only statement in the Lambda, so it was easy an convenient to do a one-liner. 

The example above assumes a console program, but the asynchronous parts of LINQ to Twitter were added specifically to support Silverlight. Here's the Silverlight example, which performs more detailed logic in a multi-line lambda, with error handling:


            m_twitterCtx.UpdateStatus(TweetTextBox.Text,
                updateResp => Dispatcher.BeginInvoke(() =>
                {
                    switch (updateResp.Status)
                    {
                        case TwitterErrorStatus.Success:
                            Status tweet = updateResp.State;
                            User user = tweet.User;
                            UserIdentifier id = user.Identifier;
                            MessageBox.Show(
                                "User: " + id.ScreenName +
                                ", Posted Status: " + tweet.Text,
                                "Update Successfully Posted.",
                                MessageBoxButton.OK);
                            break;
                        case TwitterErrorStatus.TwitterApiError:
                        case TwitterErrorStatus.RequestProcessingException:
                            MessageBox.Show(
                                updateResp.Error.ToString(),
                                updateResp.Message,
                                MessageBoxButton.OK);
                            break;
                    }
                }));

To get a feel for how this works, run the Silverlight demo, set some breakpoints, and step through the code.

Hope this helps,

Joe

Feb 24, 2011 at 2:13 PM

The one liner cod you wrote works into my Application...

But using 

updateResp => Dispatcher.BeginInvoke(() =>
                {
                    switch (updateResp.Status)
                    {
                        case TwitterErrorStatus.Success:
                            Status tweet = updateResp.State;
                            User user = tweet.User;
                            UserIdentifier id = user.Identifier;
                            MessageBox.Show(
                                "User: " + id.ScreenName +
                                ", Posted Status: " + tweet.Text,
                                "Update Successfully Posted.",
                                MessageBoxButton.OK);
                            break;
                        case TwitterErrorStatus.TwitterApiError:
                        case TwitterErrorStatus.RequestProcessingException:
                            MessageBox.Show(
                                updateResp.Error.ToString(),
                                updateResp.Message,
                                MessageBoxButton.OK);
                            break;
                    }
                }

I get Error 3 Cannot convert lambda expression to type 'string' because it is not a delegate type 

Is it because my Application is not Silverlight,

I have using System.Linq; at the beginning

What am I missing, another reference ?

Is it because my App is not in Silverlight ?

Thanks so much for taking the time Joe, very much appreciated.


Feb 24, 2011 at 2:28 PM

Ok found the solution I had to explicitly cast the lambda expression to the correct delegate type

Why LinqToTwitter example didn't need that cast ? I don't know...

UpdateStatus(txtLocation.Text, updateResp => Dispatcher.BeginInvoke( (Action) delegate () {

	 test = updateResp.Status.ToString();

         }));

Coordinator
Feb 24, 2011 at 4:34 PM

The example was from the Silverlight demo.  Silverlight uses a different set of libraries.

Joe

Feb 24, 2011 at 5:04 PM

Can you or someone explain why the line

test = answer.Status.ToString();
never gets hit...

 

Action<LinqToTwitter.TwitterAsyncResponse<LinqToTwitter.User>> messageTarget;
                string test = "";
                if (txtProfileImagePath.Text.Length != 0)
                {
                    messageTarget = delegate(LinqToTwitter.TwitterAsyncResponse<LinqToTwitter.User> answer)
                    {
                        test = answer.Status.ToString();
                    };
                    authContext.UpdateAccountImage(txtProfileImagePath.Text.ToString(), messageTarget);

                }
Coordinator
Mar 6, 2011 at 9:38 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Mar 7, 2011 at 2:19 AM

Just following up - I fixed this and included it in the latest release: http://goo.gl/1i97X.

Joe