如何异步地检索多个网站?

11 浏览
0 Comments

如何异步地检索多个网站?

使用Silverlight Windows Phone 8.1项目\n我正在尝试从网站加载数据。然而,我必须首先在该网站进行身份验证。\n所以我对该网站进行了一次提交,使用了稍作修改的CookieAwareWebClient,来自这里。\n

class CookieAwareWebClient : WebClient
{
    public CookieContainer Cookies = new CookieContainer();
    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = base.GetWebRequest(address);
        if (request is HttpWebRequest)
            (request as HttpWebRequest).CookieContainer = Cookies;
        return request;
    }
}

\n现在我使用WebClient发送带有用户名和密码的POST请求,并在我的DownloadStringCompleted事件处理程序中继续获取我的网站数据。\n到目前为止都还好。\n现在我想扩展一下,获取多个网站。\n我不必一次获取它们,事实上,最好一个接一个地获取它们。\n但是我不知道如何处理这个问题。\n到目前为止我的代码如下:\n

using System;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Windows.Web.Http;
using Microsoft.Phone.Shell;
using StackOverflowApp.Resources;
namespace StackOverflowApp
{
    public partial class MainPage
    {
        private const string URL_DATES = @"/subsite/dates";
        private const string URL_RESULTS = @"/subsite/results";
        private readonly ApplicationBarIconButton btn;
        private int runningOps = 0;
        //Regex's to parse websites
        private readonly Regex regexDates = new Regex(AppResources.regexDates);
        private readonly Regex regexResults = new Regex(AppResources.regexResults);
        private readonly CookieAwareWebClient client = new CookieAwareWebClient();
        private int status;
        // Konstruktor
        public MainPage()
        {
            InitializeComponent();
            btn = ((ApplicationBarIconButton)ApplicationBar.Buttons[0]);
            // = application/x-www-form-urlencoded
            client.Headers[HttpRequestHeader.ContentType] = AppResources.ContentType;
            client.UploadStringCompleted += UploadStringCompleted;
            client.DownloadStringCompleted += DownloadStringCompleted;
        }
        private void GetSite()
        {
            const string POST_STRING = "name={0}&password={1}";
            var settings = new AppSettings();
            if (settings.UsernameSetting.Length < 3 || settings.PasswordSetting.Length < 3)
            {   
                MessageBox.Show(
                    (settings.UsernameSetting.Length < 3 
                        ? "Please enter a username in the settings\r\n" : string.Empty) 
                    +
                    (settings.PasswordSetting.Length < 3
                        ? "Please enter a password in the settings\r\n" : string.Empty)
                );
                return;
            }
            LoadingBar.IsEnabled = true;     
            LoadingBar.Visibility = Visibility.Visible;
            client.UploadStringAsync(
                new Uri(AppResources.BaseAddress + "subsite/login"),
                "POST",
                string.Format(POST_STRING, settings.UsernameSetting, settings.PasswordSetting));
        }
        private void LoadDates()
        {
            status = 0; //Termine   
            runningOps++;
            client.DownloadStringAsync(new Uri(AppResources.BaseAddress + URL_DATES));
        }
        private void LoadResults()
        {
            status = 1; //Ergebnisse      
            runningOps++;
            client.DownloadStringAsync(new Uri(AppResources.BaseAddress + URL_RESULTS));
        }
        private void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            runningOps--;
            if (runningOps == 0)
            {
                //alle Operationen sind fertig 
                LoadingBar.IsEnabled = false;
                LoadingBar.Visibility = Visibility.Collapsed;
                btn.IsEnabled = true;
            }
            if (e.Cancelled || e.Error != null) return;
            //Antwort erhalten
            var source = e.Result.Replace("\r", "").Replace("\n", "");
            switch (status)
            {
                case 0: //Termine geladen
                    foreach (Match match in regexDates.Matches(source))
                    {
                        var tb = new TextBlock();
                        var g = match.Groups;
                        tb.Text = string.Format(
                            "{1} {2} {3}{0}{4} {5}{0}{6}",
                            Environment.NewLine,
                            g[1].Value,
                            g[2].Captures.Count > 0 ? g[2].Value : string.Empty,
                            g[3].Captures.Count > 0 ? "- " + g[3].Value : string.Empty,
                            g[5].Value,
                            g[6].Captures.Count > 0 ? "bei " + g[6].Value : string.Empty,
                            (
                                g[7].Captures.Count > 0
                                    ? g[7].Value 
                                    : string.Empty 
                            )
                                + 
                            (
                                g[8].Captures.Count > 0
                                    ? g[8].Value != g[4].Value
                                        ? g[8].Value + " != " + g[4].Value
                                        : g[8].Value
                                    : g[4].Captures.Count > 0
                                        ? g[4].Value
                                        : string.Empty
                            )
                            );
                        DatesPanel.Children.Add(tb);
                    }
                    break;
                case 1: //Ergebnisse geladen
                    foreach (Match match in regexResults.Matches(source))
                    {
                        var tb = new TextBlock();
                        var g = match.Groups;
                        tb.Text = string.Format(
                            "{1} {2} {3}{0}{4} {5}{0}{6}",
                            Environment.NewLine,
                            g[1].Value,
                            g[2].Captures.Count > 0 ? g[2].Value : string.Empty,
                            g[3].Captures.Count > 0 ? "- " + g[3].Value : string.Empty,
                            g[5].Value,
                            g[6].Captures.Count > 0 ? "bei " + g[6].Value : string.Empty,
                            (
                                g[7].Captures.Count > 0
                                    ? g[7].Value 
                                    : string.Empty 
                            )
                                + 
                            (
                                g[8].Captures.Count > 0
                                    ? g[8].Value != g[4].Value
                                        ? g[8].Value + " != " + g[4].Value
                                        : g[8].Value
                                    : g[4].Captures.Count > 0
                                        ? g[4].Value
                                        : string.Empty
                            )
                            );
                        ResultsPanel.Children.Add(tb);
                    }
                    break;
                default:
                    return;
            }
        }
        void UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
        {
            //Login completed
            LoadDates();
            //THIS WOULD YIELD AN ERROR FROM THE WEBCLIENT SAYING IT ISNT SUPPORTING MULTIPLE ASYNC ACTIONS
            //LoadResults();
        }
        private async void ClickOnRefresh(object sender, EventArgs e)
        {
            var isUp = await IsUp();
            if (isUp)
                GetSite();
            else                                                         
                MessageBox.Show("The site is down! :(");
        }
        private void ClickOnSettings(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/Settings.xaml", UriKind.Relative));
        }
        private async Task IsUp()
        {
            btn.IsEnabled = false;
            const string ISUPMELINK = "http://www.isup.me/{0}";
            var data = await RequestData(string.Format(ISUPMELINK, AppResources.BaseAddress.Replace("https://", string.Empty)));
            var isUp = !data.Contains("It's not just you!");
            btn.IsEnabled = true;
            return isUp;
        }
        private async void ClickOnTestConnection(object sender, EventArgs e)
        {
            var isUp = await IsUp();
            MessageBox.Show(string.Format("The site is {0}! :{1}", isUp ? "up" : "down", isUp ? ")" : "("));
        }
        private static async Task RequestData(string url)
        {
            using (var httpClient = new HttpClient())
                return await httpClient.GetStringAsync(new Uri(url));
        }
    }
}

\n我尝试过/我期望的/阻碍我的是:\n

    \n

  • 我最初的想法是让所有操作异步进行,并在所有请求上使用await。\n所以我进行了研究,发现WebClient有一个新的async/await实现。\nWebClient.DownloadStringTaskAsync但是我在我的WebClient中找不到这个方法,所以我认为目前WP8.1没有实现。
  • \n

  • 第二个想法是使用我已经使用的HttpClient.GetStringAsync(URI)方法,该方法支持async/await。\n正如我所说,我需要一个Cookie与请求一起使用,所以我进行了研究,找到了这个。\n然而,我找不到HttpClientHandler,也没有HttpClient.CookieContainer或类似的属性。
  • \n

  • 我还尝试等待一个站点完成,然后再进行下一个,但是我阻塞了我的GUI线程,不想在单独的线程中编写整个事件处理程序,也不知道如何高效地实现。
  • \n

0
0 Comments

从这篇文章中,我们得知作者遇到了一个问题,即如何异步地检索多个网站。作者找到了一个解决方法,即使用WebClient的DownloadStringTaskAsync方法,并导入了Microsoft Async的NuGet包。根据作者提供的链接,我们可以进一步了解异步和等待的用法。

0