Search code examples
c#func

The return of my inner func callback isn't waited


I don't really know how to name the question so, you're welcome to edit it.

This is my function :

public static KeyValuePair<bool, string> IsAuthenticated(Token token)
    {
        List<KeyValuePair<string, string>> parameters = new List<KeyValuePair<string, string>>();
        parameters.Add(new KeyValuePair<string, string>("token", token.ToString()));
        parameters.Add(new KeyValuePair<string, string>("creation_date", token.Creation_date));

        //MESSAGE
        if (!Plugin.Connectivity.CrossConnectivity.Current.IsConnected)
            return (new KeyValuePair<bool, string>(false, "No connectivity."));

        else
        {
            HttpHandler.Post(HttpHandler.ApiAddresses.ISAUTHENTICATED, parameters, (object response, bool isOk) =>
            {
                if (isOk)
                {
                    return (new KeyValuePair<bool, string>(isOk, ""));
                }
                else
                {
                    return (new KeyValuePair<bool, string>(isOk, (response as Exception).Message));
                }
            });
        }

        return (new KeyValuePair<bool, string>(false, "isAuthenticated() didn't worked.."));
    }

So, basically, I would like to avoid the last return, but if I do, then I have a warning -> All code path doesn't return a value blablabla

But my real problem is that, I would like my delegate func (or whatever you call it) to return the final value.

This is the HttpHandle.Post() function :

public static async void Post(string url, List<KeyValuePair<string, string>> parameters, Func<object, bool, KeyValuePair<bool, string>> callback)
    {
        try
        {
            HttpClient httpClient = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage();
            httpClient.BaseAddress = new Uri(url);
            var content = new FormUrlEncodedContent(parameters);
            HttpResponseMessage response = await httpClient.PostAsync(url, content);
            callback(await response.Content.ReadAsStringAsync() as object, true);
        }
        catch (Exception e)
        {
            callback(e as object, false);
        }
    }

Because each time, I only reach the "isAuthenticated() didn't worked.." return.. Maybe I don't understand something or I'm just totally wrong, please explain to me..

Thank for any help !


Solution

  • I think Post should return a Task<KeyValuePair<...>> rather than void. Then you can either make IsAuthenticated async as well and await the results from Post (which should just be returning whatever callback returns) or you may be able to get away with calling Result or Wait on it but be aware that this is a frequent source of deadlocks - it's better, if possible, to push async all the way up the call stack.

    So, Post would be:

    public static async Task<KeyValuePair<bool, string>> Post(string url, List<KeyValuePair<string, string>> parameters, Func<object, bool, KeyValuePair<bool, string>> callback)
        {
            try
            {
                HttpClient httpClient = new HttpClient();
                HttpRequestMessage request = new HttpRequestMessage();
                httpClient.BaseAddress = new Uri(url);
                var content = new FormUrlEncodedContent(parameters);
                HttpResponseMessage response = await httpClient.PostAsync(url, content);
                return callback(await response.Content.ReadAsStringAsync() as object, true);
            }
            catch (Exception e)
            {
                return callback(e as object, false);
            }
        }
    

    The problem with async void is that it will complete its work at some future point in time and it doesn't give you any means of tracking that and knowing when it has been done. That's why it's usually best avoided outside of event handlers.