6

I'm converting the data access layer of an old app from MySql to Salesforce using WinForms, DeveloperForce, Visual Studio 2015, .Net 4.6.1, C#. This is my first real TPL/async/await project.

I'm stuck on how to call ForceClient.UserInfo synchronously.

Anyway, this works:

public ForceClient Connect(){
    if (_forceClient == null){
        _auth = new AuthenticationClient();
        _auth.UsernamePasswordAsync(...).Wait();
        _forceClient = new ForceClient(_auth.InstanceUrl, _auth.AccessToken, _auth.ApiVersion);
    }
    return _forceClient;
}
...
private async Task<int> GetSomeData(){
    var response = await Force.Connect().QueryAsync<dynamic>("SELECT...").ConfigureAwait(false);
    //load data to local storage
    return response.Count
}

So far so good - The connect() blocks the first time until it connects, then I send all my queries at once and load them in pseudo parallel as the results are returned. Yay. Now I want to add a synchronous call to ForceClient.UserInfo() toward the end of the connect method.

This works asyncronously:

userInfo = await _forceClient.UserInfo<UserInfo>(UserInfoEndpointUrl);

But all my attempts to call it synchronously have failed. I've tried .Wait(), .RunSynchronously(), Task.WaitAll, Task.WaitAny, ConfigureAwait(false),... Most things I try end up causing the call to hang indefinitely (thread deadlock)

Help? Thanks!

3
  • Is there an Exception occurring? Possibly based on the UserInfoEndpointUrl being null, empty, or not a well formed Uri? See UserInfo Commented Oct 14, 2016 at 0:57
  • From the examples you should be passing the AuthenticationClient.Id as the UserInfoEndpointUrl. Commented Oct 14, 2016 at 0:59
  • Thanks @DanielBallinger - In a small test program, I am able to get this to work asynch: userInfo = await _forceClient.UserInfo<UserInfo>("test.salesforce.com/services/oauth2/userinfo"); but not userInfo = await _forceClient.UserInfo<UserInfo>(auth.id); I think the real problem I struggling with is trying to call it with the .configureAwait(false). I can't seem to avoid a threading deadlock.
    – Jeff
    Commented Oct 17, 2016 at 0:08

1 Answer 1

2

Update based on comments.

You need to use Task.ConfigureAwait(false); to prevent blocking the UI thread context.

See Don't Block on Async Code


I made the call synchronously using the following:

class Program
{
    static void Main(string[] args)
    {
        Task.Run(async () =>
        {
            MainAsync(args);
        }).Wait();

        Thread.Sleep(1000);
        Console.WriteLine("Done");
    }

    static async Task MainAsync(string[] args)
    {
        try
        {
            var auth = new AuthenticationClient();
            auth.UsernamePasswordAsync("ConsumerName", "ClientSecret", "[email protected]", "password goes here").Wait();

            var forceClient = new ForceClient(auth.InstanceUrl, auth.AccessToken, auth.ApiVersion);

            // Without the Thread.Sleep above the application will often close before the result comes back.
            //var userInfo = await forceClient.UserInfo<UserInfo>(auth.Id);
            //Console.WriteLine(userInfo.FirstName);

            var task = forceClient.UserInfo<UserInfo>(auth.Id);
            task.Wait();
            var userInfo2 = task.Result;
            Console.WriteLine(userInfo2.FirstName);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

If I made the call asynchronously and didn't have the Thread.Sleep(1000) the application would close before the UserInfo came back.

Note that the usage of Task.Wait and Task.Result isn't ideal as an exception within the Task will be wrapped in an AggregateException.

See also:

2
  • I can make something like the above work in a console app, but not in my winforms app. The calls like: var response = await Force.Connect().QueryAsync<dynamic>(soql) were also hanging until I added the .ConfigureAwait(false);
    – Jeff
    Commented Oct 17, 2016 at 0:16
  • @Jeff Good to know. Sounds like the deadlock occured on the UI thread when it blocked on the Task. Commented Oct 17, 2016 at 1:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .