在Windows Phone应用程序中,从DownloadStringCompleted处理器中填充并返回实体

本文关键字:填充 处理器 实体 返回 DownloadStringCompleted Windows Phone 应用程序 | 更新日期: 2023-09-27 17:52:57

我有一个从url获取HTML的方法,通过解析它提取实体,并返回实体列表。下面是示例代码:

  public List<Entity> FetchEntities()
    {
        List<Entity> myList = new List<Entity>();
        string url = "<myUrl>";
        string response = String.Empty;
        client = new WebClient();
        client.DownloadStringCompleted += (sender, e) =>
        {
            response = e.Result;
            // parse response
            // extract content and generate entities
            // <---- I am currently filling list here
        };
        client.DownloadStringAsync(new Uri(url));
        return myList;
    }

问题是,当异步调用正在进行时,控制返回空myList。我该如何预防呢?我的最终目标是返回填充的列表。

而且这个方法在一个单独的类库项目中并且从windows phone应用程序中被调用我必须保持它只是那样。有什么办法做到这一点,还是我错过了什么?

在Windows Phone应用程序中,从DownloadStringCompleted处理器中填充并返回实体

您可以像这样传递回调给方法并使其不带任务而异步,因此您必须稍微更新方法用法。

public void FetchEntities(
    Action<List<Entity>> resultCallback, 
    Action<string> errorCallback)
{
    List<Entity> myList = new List<Entity>();
    string url = "<myUrl>";
    string response = String.Empty;
    client = new WebClient();
    client.DownloadStringCompleted += (sender, e) =>
    {
        response = e.Result;
        // parse response
        // extract content and generate entities
        // <---- I am currently filling list here
        if (response == null)
        {
            if (errorCallback != null)
                errorCallback("Ooops, something bad happened");
        }
        else
        {
            if (callback != null)
                callback(myList);
        }
    };
    client.DownloadStringAsync(new Uri(url));
}

另一个选项是强制它是同步的。这样的

public List<Entity> FetchEntities()
{
    List<Entity> myList = new List<Entity>();
    string url = "<myUrl>";
    string response = String.Empty;
    client = new WebClient();
    AutoResetEvent waitHandle = new AutoResetEvent(false);
    client.DownloadStringCompleted += (sender, e) =>
    {
        response = e.Result;
        // parse response
        // extract content and generate entities
        // <---- I am currently filling list here
        waitHandle.Set();
    };
    client.DownloadStringAsync(new Uri(url));
    waitHandle.WaitOne();
    return myList;
}

这就是异步编程非阻塞的要点。你可以将回调作为参数传递,并在其他地方处理结果,而不是尝试返回它。

如果你需要返回结果,你可以使用这个TPL库,我已经使用它没有问题一段时间了。

public Task<string> GetWebResultAsync(string url)
     {
         var tcs = new TaskCompletionSource<string>();
         var client = new WebClient();
         DownloadStringCompletedEventHandler h = null;
         h = (sender, args) =>
                 {
                     if (args.Cancelled)
                     {
                         tcs.SetCanceled();
                     }
                     else if (args.Error != null)
                     {
                         tcs.SetException(args.Error);
                     }
                     else
                     {
                         tcs.SetResult(args.Result);
                     }
                     client.DownloadStringCompleted -= h;
                 };
         client.DownloadStringCompleted += h;
         client.DownloadStringAsync(new Uri(url));
         return tcs.Task;
     }
}

调用它正是你在。net 4.0中使用TPL的方式

GetWebResultAsnyc(url).ContinueWith((t) => 
                                    {
                                         t.Result //this is the downloaded string
                                    });

或:

var downloadTask = GetWebResultAsync(url);
downloadTask.Wait();
var result = downloadTask.Result; //this is the downloaded string

希望这对你有帮助