多线程下载在 dataGridView显示的问题?
新手,想用c#做个下载器,界面如上图,遇到问题是当一个个下载正在下载时,如果再添加一个下载,第一个下载的状态显示原本是应该在第一行显示的,可以添加第二个下载后,第一个下载和第二个下载的状态都显示到第二行了。
下载类代码
public partial class DownList : UserControl
{
private string[] info = null;
private string FileSize; // 下载文件总大小
private string FileTempSize; // 已下载文件大小
private int FileSpeed; // 实时下载速度
private int FileTemp; // 临时下载缓冲
private Form1 frm;
public static int rNum = -1;
public DownList(string[] Temp, Form1 form)
{
info = Temp;
frm = form;
rNum++;
}
public void DownList_Load()
{
frm.dataGridView1["status", rNum].Value = frm.imageList1.Images[2]; //显示下载状态图片
frm.dataGridView1["name", rNum].Value = Path.GetFileName(info[0]);
Thread Th = new Thread(new ParameterizedThreadStart(DownFile)); //创建下载线程
Th.IsBackground = true; //设置为后台线程,当主窗体关闭时,同时关闭线程
Th.Start(info); //启动线程
}
private void DownFile(object url)
{
string[] urlt = (string[])url; //转换类型
string[] str = new string[3]; //创建信息保存变量
long strTemp = 0; //已下载文件长度保存
FileStream Fs = new FileStream(urlt[1], FileMode.Create); //创建保存文件对象
int count; //读取字节长度
try
{
/* 开始通讯 */
HttpWebRequest Hwr = (HttpWebRequest)WebRequest.Create(urlt[0]);
HttpWebResponse rps = (HttpWebResponse)Hwr.GetResponse();
str[0] = rps.StatusCode.ToString(); //获取服务器响应状态
str[1] = rps.ContentLength.ToString(); //获取文件长度
frm.dataGridView1["server", rNum].Value = str[0];
Stream stream = rps.GetResponseStream(); //获取服务器响应文件流
byte[] byts = new byte[rps.ContentLength]; //创建字节数组保存文件流
System.Threading.Timer FileTm = new System.Threading.Timer(SpeedTimer, null, 0, 1000);
while ((count = stream.Read(byts, 0, 5000)) != 0)
{
FileTemp += count;
str[2] = (strTemp += count).ToString(); //获取已下载文件长度
Fs.Write(byts, 0, count); //将已下载部分写入文件
SetLblText(str,rNum); //将结果传递给方法进行实时显示
}
/* 关闭流 */
rps.Close();
stream.Close();
Fs.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); //如发生错误,弹窗报错误描述
Fs.Close();
}
}
private void SpeedTimer(object state)
{
FileSpeed = FileTemp / 1;
FileTemp = 0;
}
private delegate void SetString(string[] str,int rowNum);
private void SetLblText(string[] str,int rowNum)
{
if (InvokeRequired)
{
SetString SS = new SetString(SetLblText);
Invoke(SS, new object[] { str,rowNum });
}
else
{
if (str[0] != "OK")
{
frm.dataGridView1["server", rowNum].Value = str[0];
frm.dataGridView1["status", rowNum].Value = frm.imageList1.Images[1];
}
/* 显示下载进度,更新dataGridView */
FileSize = SizeConversion(Convert.ToInt64(str[1]));
FileTempSize = SizeConversion(long.Parse(str[2]));
frm.dataGridView1["size", rowNum].Value = FileTempSize + "/" + FileSize;
frm.dataGridView1["speed", rowNum].Value = SizeConversion(FileSpeed) + "/s";
int intp = int.Parse(str[1]) - int.Parse(str[2]);
int time;
if (intp != 0 && FileSpeed != 0)
{ time = intp / FileSpeed; }
else
{ time = 0; }
TimeSpan ts = new TimeSpan(0, 0, time);
frm.dataGridView1["retime", rowNum].Value = (int)ts.TotalHours + ":" + ts.Minutes + ":" + ts.Seconds;
int temp = Convert.ToInt32(float.Parse(str[2]) / float.Parse(str[1]) * 100);
frm.dataGridView1["progress", rowNum].Value = temp;
if (str[1] == str[2])
{ frm.dataGridView1["status", rowNum].Value = frm.imageList1.Images[0]; }
}
}
/// <summary>
/// 文件大小换算
/// </summary>
/// <param name="bytes">文件长度</param>
/// <returns></returns>
private static string SizeConversion(long bytes)
{
int unit = 1024;
if (bytes < unit) return bytes + " B";
int exp = (int)(Math.Log(bytes) / Math.Log(unit));
return String.Format("{0:F1} {1}B", bytes / Math.Pow(unit, exp), "KMGTPE"[exp - 1]);
}
}
Form1窗口代码:
private void button4_Click(object sender, EventArgs e) //开始下载按钮
{
dataGridView1.Rows.Add();
string[] UrlPath = new string[2]; //下载地址和文件保存路径
UrlPath[0] = textBox2.Text; //下载地址
UrlPath[1] = textBox1.Text;
DownList dl = new DownList(UrlPath,this);
dl.DownList_Load();
}
求助大神啊!
------解决方案--------------------
SetLblText(str,rNum); //将结果传递给方法进行实时显示
rNum是全局变量,存的最大行号,你应该Th.Start(info);传到线程里
*****************************************************************************
http://feiyun0112.cnblogs.com/