×

Loading...

一个WPF Demo Project,显示了Async + Await的优势

Project的目的很简单,根据 http://rolia.net 找到论坛入口URI =>从所有论坛中找到“科技领域杂谈”URI=> 在“科技领域杂谈”帖子中找到我的第一个帖子URI=> 显示我的帖子的原始HTML信息

每一步都是一个单独的异步操作,每一步都依靠上一步操作的结果

比较费时间的是根据原始的HTML Parse出需要的URI,不过如果你对LINQ很熟悉,这也就是分分钟的事情,不过在这个程序里这一块是凑或完成的,因为是为了演示async + await异步操作,这一步不是重点

这是一个WPF的Project,自己创建一个WPF的Project,分别把XAML和Code Behind Copy进去就好,直接可以运行。第一次运行整个window会卡住,我也不知道为什么,可能是WebClient在后台建立Socket连接,但是第二次、第三次就好了。在windows phone 里我没遇到过这种情况

第一个按钮是传统的异步方式,第二个按钮是Async+Await方式

XAML:
<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
    <StackPanel>
        <Button Content="Go to Rolia, Normal Async Usage" x:Name="butonNormalAsync" Click="butonNormalAsync_Click"/>
        <Button Content="Go to Rolia, Async + Await" x:Name="buttonAsyncAwait" Click="buttonAsyncAwait_Click"/>
        <TextBox x:Name="textBlock1" Height="200" TextWrapping="Wrap" ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
    </StackPanel>
</Window>


Code Behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        string baseForumURI = "http://www.rolia.net"; // 论坛入口的URI
        string forumEntryURI; // should be http://www.rolia.net/f // 论坛URI
        string scienceForumEntryURI; // 科技领域杂谈的URI
        string firstThreadURL; // 我的第一篇帖子的URI

        string htmlString;


        // 传统的异步方式,就一个字:乱
        private void butonNormalAsync_Click(object sender, RoutedEventArgs e)
        {            
            WebClient wc = new WebClient();
            wc.DownloadDataCompleted += (s, e1) =>
                {
                    htmlString = System.Text.Encoding.GetEncoding("UTF-8").GetString(e1.Result);
                    forumEntryURI = getForumEntryURI(htmlString);

                    WebClient wc1 = new WebClient();
                    wc1.DownloadDataCompleted += (s2, e2) =>
                        {
                            htmlString = System.Text.Encoding.GetEncoding("UTF-8").GetString(e2.Result);
                            scienceForumEntryURI = getScientForumEntry(htmlString);

                            WebClient wc2 = new WebClient();
                            wc2.DownloadDataCompleted += (s3, e3) =>
                                {
                                    htmlString = System.Text.Encoding.GetEncoding("UTF-8").GetString(e3.Result);
                                    firstThreadURL = getFirstThreadURL(htmlString);
                              
                                    //ok now, we came to the last step: show the content of my thread
                                    WebClient wc3 = new WebClient();
                                    wc3.DownloadDataCompleted += (s4, e4) =>
                                        {
                                            htmlString = System.Text.Encoding.GetEncoding("UTF-8").GetString(e4.Result);
                                            buttonAsyncAwait.Dispatcher.BeginInvoke(new Action(() => textBlock1.Text = htmlString));
                                        };
                                    //从我的第一篇帖子的URI download content
                                    wc3.DownloadDataAsync(new Uri(firstThreadURL));
                                };
                            // step 3: 从“科技领域杂谈” 找到我的第一篇帖子
                            wc2.DownloadDataAsync(new Uri(scienceForumEntryURI));
                        };
                    // step 2: 从论坛列表找到“科技领域杂谈”
                    wc1.DownloadDataAsync(new Uri(forumEntryURI));
                };
            // step 1: 从rolia.net找到论坛入口
            wc.DownloadDataAsync(new Uri(baseForumURI));
        }

        // Async + Await 异步方式
        private async void buttonAsyncAwait_Click(object sender, RoutedEventArgs e)
        {
            WebClient wc = new WebClient();

            // step 1: 从rolia.net找到论坛入口
            byte[] resultBytes = await wc.DownloadDataTaskAsync(baseForumURI);
            htmlString = System.Text.Encoding.GetEncoding("UTF-8").GetString(resultBytes);
            forumEntryURI = getForumEntryURI(htmlString);

            // step 2: 从论坛列表找到“科技领域杂谈”
            resultBytes = await wc.DownloadDataTaskAsync(forumEntryURI);
            htmlString = System.Text.Encoding.GetEncoding("UTF-8").GetString(resultBytes);
            scienceForumEntryURI = getScientForumEntry(htmlString);

            // step 3: 从“科技领域杂谈” 找到我的第一篇帖子
            resultBytes = await wc.DownloadDataTaskAsync(scienceForumEntryURI);
            htmlString = System.Text.Encoding.GetEncoding("UTF-8").GetString(resultBytes);
            firstThreadURL = getFirstThreadURL(htmlString);

            //从我的第一篇帖子的URI download content
            resultBytes = await wc.DownloadDataTaskAsync(firstThreadURL);
            htmlString = System.Text.Encoding.GetEncoding("UTF-8").GetString(resultBytes);

            // show the raw content of my thread in the textBox
            textBlock1.Text = htmlString;
        }

        // parse HTML to ForumEntryURI
        string getForumEntryURI(string htmlString)
        {
            int index1 = htmlString.IndexOf("枫下论坛");
            int index2 = htmlString.Substring(0,index1).LastIndexOf(@"<a");
            string result = htmlString.Substring(index2, index1 - index2);
            result = result.Split(' ').First(s => s.Contains("href")).TrimEnd('>','\n','\t').Split('=').Last().Trim('\"');
            return string.Format("{0}{1}",baseForumURI, result);
        }

        // parse HTML to ScientForumEntry
        private string getScientForumEntry(string htmlString)
        {
            int index1 = htmlString.IndexOf("科技领域杂谈");
            int index2 = htmlString.Substring(0, index1).LastIndexOf(@"<a");
            string result = htmlString.Substring(index2, index1 - index2);
            result = result.Split(' ').First(s => s.Contains("href")).Substring("href=".Length).Trim('\'');
            return string.Format("{0}/{1}", forumEntryURI, result);
        }

        // parse HTML to FirstThreadURL
        private string getFirstThreadURL(string htmlString)
        {
            int index1 = htmlString.IndexOf("binghongcha76");
            index1 = htmlString.Substring(0, index1).LastIndexOf(@"<a");
            int index2 = htmlString.Substring(0, index1).LastIndexOf(@"<a");

            string result = htmlString.Substring(index2, index1 - index2);
            result = result.Split(' ').First(s => s.Contains("href")).Substring("href=".Length).Trim('\'');
            return string.Format("{0}/{1}", forumEntryURI, result);
        }
    }
}
Sign in and Reply Report