想实现一个下载程序 ,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("没有输入要下载的文件!");
}
}
这个错误我发现时走到了保存位置按钮时候 我把它删除了 没有那个提示了。
现在是提示从不是创建控件“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("没有输入要下载的文件!");
}
}
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(); }
这个方法虽然方便快捷,意思是取消线程间数据访问时候的检测,但这样是会使线程不安全,对小系统就没多大影响、
最好用 委托
你用子线程创建 UI控件或者 访问 UI控件,那么 子线程创建的 UI 是和 子线程一起结束还是 和 程序一起结束??所以,在线程编程中:所有的 UI控件 都只能由 主线程操作,子线程对 UI控件的访问,操作,创建 都会引发这个问题;你要使用委托,告诉主线程,你现在要将UI控件 操作成什么样子,让主线来替你的子线程完成UI控件的修改;而不是子线程自己就上手做事;