简体   繁体   中英

Returning a String in an Async Event Handler

I need to return a String that I get from an Async Event Handler. I can't currently do this as if I try returning inside the handler, it gives me an error telling me I can't return any objects because the handler is supposed to return void.

Here is my code:

    public String Login(String username, String password)
    {
        String returningData = "";
        Dictionary<string, object> parameters = new Dictionary<string, object>();
        parameters.Add("user", username);
        parameters.Add("pass", password);

        PostClient client = new PostClient(parameters);
        client.DownloadStringCompleted += (senders, ex) =>
            {
                if (ex.Error == null)
                {
                    //Process the result...
                    return ex.Result;
                }
                else
                {
                    return "An error occurred. The details of the error: " + ex.Error;
                }
            };
        client.DownloadStringAsync(new Uri("http://www.site.com/sample.php", UriKind.Absolute));
    }

How can I return ex.Result/error message correctly?

You can have the method return a Task<string> rather than a string. The method won't return a value right when it's called, calling the method will start the work and the task can be completed at some point in the future. You can use a TaskCompletionSource to create the task to be returned.

public Task<string> Login(String username, String password)
{
    var tcs = new TaskCompletionSource<string>();
    Dictionary<string, object> parameters = new Dictionary<string, object>();
    parameters.Add("user", username);
    parameters.Add("pass", password);

    PostClient client = new PostClient(parameters);
    client.DownloadStringCompleted += (senders, ex) =>
    {
        if (ex.Error == null)
        {
            //Process the result...
            tcs.TrySetResult(ex.Result);
        }
        else
        {
            string errorMessage = "An error occurred. The details of the error: " + ex.Error;
            //todo use a more derived exception type
            tcs.TrySetException(new Exception(errorMessage));
        }
    };
    client.DownloadStringAsync(new Uri("http://inkyapps.mobilemp.net/scripts/PHP/socialnet/login.php", UriKind.Absolute));

    return tcs.Task;
}

Simply fire an event to notify "outside world" about completion of operation.

For this define your delegate:

public void delegate OnError(object sender, string message);
public event OnError OnErrorEvent; 

...



           client.DownloadStringCompleted += (senders, ex) =>
            {
                if (ex.Error == null)
                {
                    //Process the result...
                    return ex.Result;
                }
                else
                {
                   if(OnErrorEvent != null)
                   OnErrorEvent(this, "An error occurred. The details of the error: " + ex.Error;);
                }
            };

This is just an example, you have to choose more approriate signature of delegate for your concrete case.

I would wrap this up into a Task<string> , and return that:

public Task<string> LoginAsync(String username, String password)
{
    var results = new TaskCompletionSource<string>();
    Dictionary<string, object> parameters = new Dictionary<string, object>();
    parameters.Add("user", username);
    parameters.Add("pass", password);

    PostClient client = new PostClient(parameters);
    client.DownloadStringCompleted += (senders, ex) =>
        {
            if (ex.Error == null)
            {
                results.TrySetResult(ex.Result);
            }
            else
            {
                results.TrySetException(ex.Error); // Set the exception
            }
        };
    client.DownloadStringAsync(new Uri("http://inkyapps.mobilemp.net/scripts/PHP/socialnet/login.php", UriKind.Absolute));

    return results.Task;
}

This will then allow you to use this method with the async / await keywords directly, providing proper asynchronous support and exception handling in the caller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM