2

我需要返回从异步事件处理程序获得的字符串。我目前不能这样做,就好像我尝试在处理程序中返回一样,它给了我一个错误,告诉我我不能返回任何对象,因为处理程序应该返回 void。

这是我的代码:

    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));
    }

如何正确返回 ex.Result/error 消息?

4

3 回答 3

1

您可以让该方法返回 aTask<string>而不是字符串。该方法在调用时不会立即返回值,调用该方法将开始工作,并且可以在将来的某个时间完成任务。您可以使用 aTaskCompletionSource创建要返回的任务。

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;
}
于 2013-07-22T16:05:21.640 回答
0

只需触发一个事件来通知“外部世界”关于操作的完成。

为此,请定义您的委托:

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;);
                }
            };

这只是一个例子,您必须为您的具体案例选择更合适的代表签名。

于 2013-07-22T16:01:56.217 回答
0

我会把它包装成一个Task<string>,然后返回:

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;
}

然后,这将允许您直接将此方法与async/await关键字一起使用,从而在调用者中提供适当的异步支持和异常处理。

于 2013-07-22T16:06:39.833 回答