我做了一个很简单的抓取网页的程序,将抓取到的页面显示在RichTextBox中,抓取的语句和方法我把它定义在了WebHtml类中,通过给这个类的实例对象赋值(把参数传给它)和它的GetHtml()方法来获得页面,GetHtml()返回抓到的网页字符串,并把它存在MainForm中的RichTextBox中。
代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;namespace www
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            
        }        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.backgroundWorker.CancelAsync();                   }        private void btnLogin_Click(object sender, EventArgs e)
        {            
            this.backgroundWorker.RunWorkerAsync();
            btnLogin.Enabled = false;
            btnCancel.Enabled = true;
            toolStripStatusLabel.Text = "正在抓取";
            while (this.backgroundWorker.IsBusy)
            {
                Application.DoEvents();
            }
            btnLogin.Enabled = true;
        }        private void MainForm_Load(object sender, EventArgs e)
        {
            
        }        private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            
        }        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                MessageBox.Show("你已经取消了抓取!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            else if (e.Error != null)
            {
                MessageBox.Show("抓取过程发生了错误", "失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                toolStripStatusLabel.Text = "抓取完成";
            }
            
            btnLogin.Enabled = true;
            btnCancel.Enabled = false;
        }        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
           //准备初始数据
            string url = "http://xxx.xxx.xxx";
            postData += "site_id=13&";
            postData += "data=20090128&";
            postData += "ast=13&";
            postData += "dts=13&";
            postData = postData + "id=" + textUsername.Text + '&';
            postData = postData + "pwd=" + textPassword.Text;
            //生成对象实例,将参数提交给对象webHtml
            WebHtml webHtml = new WebcHtml(url, postData);
            //将抓取的网页在richTextBox中显示
            richTextBox.Text=weHtml.GetHtml();  <=====就是这句出错了
        }
    }
}程序能通过编译并运行,只是执行到最后一步时出错了,提示是“线程间操作无效,从不是创建控件"richTextBox的线程访问它”,我确定不是我代码输错了,因为我如果不用BackgroundWork,直接将语句写在btnLogin的事件中就可以正常运行。
在此想请教2个问题:
1、我的程序哪里错了?
2、在通过HttpWepRequest抓取网页的过程中,就算点取消是不是中止不了?

解决方案 »

  1.   

    使用delegate和control.invoke来从其他线程中控制控件信息public partial class Form1 : Form
        {
            private delegate void FlushClient();//代理
            public Form1()
            {
                InitializeComponent();
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                Thread thread = new Thread(CrossThreadFlush);
                thread.IsBackground = true;
                thread.Start();
            }        private void CrossThreadFlush()
            {
                while (true)
                {
                    //将sleep和无限循环放在等待异步的外面
                    Thread.Sleep(1000);
                    ThreadFunction();
                }
            }
            private void ThreadFunction()
            {
                if (this.textBox1.InvokeRequired)//等待异步
                {
                    FlushClient fc = new FlushClient(ThreadFunction);
                    this.Invoke(fc);//通过代理调用刷新方法
                }
                else
                {
                    this.textBox1.Text = DateTime.Now.ToString();
                }
            }
        }文章来自学IT网:http://www.xueit.com/html/2009-03/21_903_00.html
      

  2.   

    richTextBox.Text=weHtml.GetHtml();  <=====就是这句错了 把weHtml.GetHtml(); 用一个串传出来。
    直接在RunWorkerCompleted这里面赋值;
      

  3.   

    BackgroundWork一般在DoWork做后台数据处理,在RunWorkerCompleted做界面的数据更新。