想实现一个下载程序 ,textbox中为下载地址,输入后点击按钮button 还有一个progressBar1显示下载进度,开始遇到的问题是:错误:在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试器附加到该进程才会引发此异常
这个错误我发现时走到了保存位置按钮时候 我把它删除了 没有那个提示了。
现在是提示从不是创建控件“progressBar1”的线程访问它的问题 这个问题如何解决呢
再一个之前的问题 如果我还是用到保存按钮的话(savefiledialog)怎么办呢 说让我加  [STAThread] main上面有  [STAThread]啊  总之想实现下载 并且我发现有几次成功时候窗体没响应了 下载实现了但是卡了半天 然后滚动条才开始走,这个是不是和开始的问题没有解决有关系呢  谢谢大家 下面是出错代码 望解答 或给予代码帮助 谢谢
  private void button1_Click(object sender, EventArgs e)
        {
            
            Thread th = new Thread(new ThreadStart(downfile));
             th.SetApartmentState(ApartmentState.STA );
            th.Start();             
        }        private void  Form1_Load(object sender, EventArgs e)
        {        }        public  void downfile()
        {
            string FileName;
            WebClient DownFile = new WebClient();
            long fbytes;
            if (textBox1.Text != "")
            {
                string s1 = textBox1.Text .ToString();                string s = s1.Substring(s1.LastIndexOf('/') + 1, s1.Length - (s1.LastIndexOf('/') + 1));
             
                FileName = s; 
                if (FileName != "")
                {
                    //取得文件大小 
                    WebRequest wr_request = WebRequest.Create(textBox1.Text);
                    WebResponse wr_response = wr_request.GetResponse();
                    fbytes = wr_response.ContentLength;
                    progressBar1.Maximum = (int)fbytes;
                    progressBar1.Step = 1;
                    wr_response.Close();
                    //开始下载数据 
                    DownFile.DownloadData(textBox1.Text);
                    Stream strm = DownFile.OpenRead(textBox1.Text);
                    StreamReader reader = new StreamReader(strm);
                    byte[] mbyte = new byte[fbytes];
                    int allmybyte = (int)mbyte.Length;
                    int startmbyte = 0;
                    while (fbytes > 0)
                    {
                        int m = strm.Read(mbyte, startmbyte, allmybyte);
                        if (m == 0) break;
                        startmbyte += m;
                        allmybyte -= m;
                        progressBar1.Value  += m;
                    }
                    FileStream fstrm = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.Write);
                    fstrm.Write(mbyte, 0, startmbyte);
                    strm.Close();
                    fstrm.Close();
                    progressBar1.Value = progressBar1.Maximum;
                }
            }
            else
            {
                MessageBox.Show("没有输入要下载的文件!");
            }
        } 

解决方案 »

  1.   

    这个不要: th.SetApartmentState(ApartmentState.STA ); 然后刷新 processBar 的应该用 Control.Invoke
      

  2.   

           progressBar1.Maximum = 120;
                worker.WorkerReportsProgress = true;
                worker.WorkerSupportsCancellation = true;
                //正式做事情的地方
                worker.DoWork += new DoWorkEventHandler(DoWork);
                //任务完称时要做的,比如提示等等
                worker.ProgressChanged += new ProgressChangedEventHandler(ProgessChanged);
                //任务进行时,报告进度
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CompleteWork);public void DoWork(object sender, DoWorkEventArgs e)
            {
                e.Result = ComputeFibonacci(worker, e);
                //获取异步操作结果的值,当ComputeFibonacci(worker, e)返回时,异步过程结束
            }        //调用 ReportProgress 时发生
            public void ProgessChanged(object sender, ProgressChangedEventArgs e)
            {
                this.progressBar1.Value = e.ProgressPercentage;
                //将异步任务进度的百分比赋给进度条           
            }        //当后台操作已完成、被取消或引发异常时发生
            public void CompleteWork(object sender, RunWorkerCompletedEventArgs e)
            {
                this.progressBar1.Visible = false;
                if (e.Cancelled)
                {
                    _IsExecuted = false;            }
                else
                {
                    _IsExecuted = true;
                }
                this.button1.Visible = true;
            }  //是否需要下载
            private bool IsNeedDownload;
            private string packageFilePath;
            private int ComputeFibonacci(object sender, DoWorkEventArgs e)
            {
                IsNeedDownload = true;
                packageFilePath = Application.StartupPath + @"\package";
                // string templateFilePath = Application.StartupPath + @"\package\template.ini";
                string strServerSysVersion = _strServerVersion;
                this.BeginInvoke(new DownbFileMonth(DownFile));
                for (int i = 1; i < 120; i++)
                {
                    // BeginInvoke —在创建控件的基础句柄所在线程上,用指定的参数异步执行指定委托
                    if (IsNeedDownload)
                    {
                        // Thread.IsAlive 属性   指示当前线程的执行状态
                        System.Threading.Thread.Sleep(500);
                        if (i == 119)
                        {
                            i = 1;
                        }
                    }
                    //worker.CancellationPending  获取应用程序是否已请求取消后台操作
                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;
                    }
                    else
                    {
                        //ReportProgress  异步操作的进度
                        worker.ReportProgress(i);
                        System.Threading.Thread.Sleep(15);
                    }
                    //判断应用程序是否取消后台操作
                }
                return -1;
            }Thread DownFileThread = null;
            private void DownFile()
            {            DownFileThread = new Thread(new ThreadStart(delegate()
                {
                    System.Net.WebClient wc = new System.Net.WebClient();
                    try
                    {                        this.label3.Text = "正在从服务器下载...";
                        wc.DownloadFile(_strServerFileUrl, _strClientDiskStorageDirectory);
                      }
                    catch
                    {
                        worker.CancelAsync();
                        worker.Dispose();
                        if (DownFileThread != null)
                        {
                            DownFileThread.Abort();
                        }
                        if (UnZipThread != null)
                        {
                            UnZipThread.Abort();
                        }
                        return;
                    }
                }));
                DownFileThread.Name = "DownFile";
                DownFileThread.IsBackground = false;
                DownFileThread.Start();        }
      

  3.   

    有个傻瓜办法  把窗体的CheckForIllegalCrossThreadCalls属性设为false  
      

  4.   

    有个傻瓜办法 把窗体的CheckForIllegalCrossThreadCalls属性设为false  
    这个方法虽然方便快捷,意思是取消线程间数据访问时候的检测,但这样是会使线程不安全,对小系统就没多大影响、
    最好用 委托
      

  5.   

    从不是创建控件“progressBar1”的线程访问它——这是线程问题:程序运行之后,主线程是和程序一起死的;子线程是在 做完自己的事情之后死的;就是说:子线程的结束 和程序的结束是不一致的;
    你用子线程创建 UI控件或者 访问 UI控件,那么 子线程创建的 UI 是和 子线程一起结束还是 和 程序一起结束??所以,在线程编程中:所有的  UI控件  都只能由  主线程操作,子线程对 UI控件的访问,操作,创建 都会引发这个问题;你要使用委托,告诉主线程,你现在要将UI控件 操作成什么样子,让主线来替你的子线程完成UI控件的修改;而不是子线程自己就上手做事;