views:

89

answers:

2

I've read some of the articles on MSDN but they're not quite what I need right now.

Could you show me a simple application that downloads a website asyncchronously (WebClient.DownloadDataAsync) and then filters the TITLE tag of the site?

I can't do this for the life of me, and I'm just trying to see a clear cut model.

+3  A: 

You may find it easier to use DownloadStringAsync. That way, you can parse the HTML as a string rather than having to deal with encoding yourself.

As far as how to parse the title, you may find that a bit more difficult to do, since .NET doesn't have a built-in HTML parser. You could try some RegEx or use XMLReader, but those can be problematic if you have malformed or tricky content.

var client = new WebClient();
client.DownloadStringCompleted += (s, args) => {
    if (args.Error == null && !args.Cancelled) {
        var regex = new Regex("<title>(?<title>.*?)</title>");
        var match = regex.Match(args.Result);
        if (match.Success)
        {
            var myTitle = match.Groups["title"].Value;
            // ... 
        }
    }
};
client.DownloadStringAsync(url);
Jacob
Hey why did you declare a var in your first line? What is a var? :S
Sergio Tapia
It's just implicit typing. Since "new WebClient()" returns a WebClient, the compiler automatically makes the "client" variable a WebClient. Means I had to do less typing, basically.
Jacob
var is a new keyword in C#3. It does NOT mean that the variable can contain anything, it just means that the compiler will infer the type based on what you assign to it
Thomas Levesque
+2  A: 

Here is a complete solution that uses asynchronous delegates. Notice that I am using Control.Invoke to ensure that any UI interactions are performed on the main UI thread, in this case displaying a message box.

var button = new Button {Text = "Run"};
button.Click +=
    (sender, e) =>
        {
            var fetchTitle = new Func<string, string>(
                address =>
                    {
                        var html = new WebClient().DownloadString(address);
                        var match = Regex.Match(html, "<title>(.*)</title>");
                        return match.Groups[1].Value;
                    });
            var displayTitle = new Action<string>(
                title => MessageBox.Show(title));
            fetchTitle.BeginInvoke(
                "http://stackoverflow.com",
                result =>
                    {
                        var title = fetchTitle.EndInvoke(result);
                        if (button.InvokeRequired)
                        {
                            button.Invoke(displayTitle, title);
                        }
                        else
                        {
                            displayTitle(title);
                        }
                    },
                null);
        };
new Form {Controls = {button}}.ShowDialog();
Nathan Baulch