c# 线程和progressbar的一个问题??????????????????????????

didiaogao 2010-11-11 09:28:56
我写了一个读取文本文件的一个功能。

文本中有很多数据。所以在读取的时候我加了一个进度条(progressbar)的控件。

我这个功能是加在我我们的系统上的。这个系统本山有一个线程。当我执行读取的时候 我的这个功能就会把系统的主线程占了。 系统的就不能操作了。。。所以我要给我的这个读取文本的功能开一个线程。

程序大概是这样的

// 开始读取按钮
private void btnStart_Click(object sender, EventArgs e)
{
System.Threading.Thread t = new System.Threading.Thread(new ThreadStart(WriteDB));
t.Start();
}

// 读取操作
private void WriteDB()
{
string wwpFolderPath = @"C:\Documents and Settings\Administrator\桌面\Placenames\乡镇街道\test.wwp";
string[] onePathList = Directory.GetFiles(wwpFolderPath, "*.wwp", SearchOption.TopDirectoryOnly);

BufferedStream dataFileStream = new BufferedStream(File.Open(onePathList[a].ToString(),FileMode.Open,FileAccess.Read, FileShare.Read));
BinaryReader dataFileReader = new BinaryReader(dataFileStream, System.Text.Encoding.GetEncoding("GB2312"));
m_numberPlacenames = dataFileReader.ReadInt32();
progressBar1.Value = 0;
progressBar1.Maximum = m_numberPlacenames;
for (int i = 0; i < m_numberPlacenames; i++)
{
pName = dataFileReader.ReadString();
pLat = dataFileReader.ReadSingle();
pLon = dataFileReader.ReadSingle();
progressBar1.PerformStep();
}
}



这样的话就有个问题。这个进度条走的特别慢。不用线程的话就很正常。。后来我发现如果把ressBar1.PerformStep();这句话注掉叶很正常。这个是怎么回事。。谁知道。谢谢
...全文
389 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
didiaogao 2010-11-12
  • 打赏
  • 举报
回复
没人回答吗
didiaogao 2010-11-12
  • 打赏
  • 举报
回复
好朋友们 你们还好吗 没人来回答???????
flyerwing 2010-11-11
  • 打赏
  • 举报
回复
这个任务进度很难计算吧,不确定性很多.
四更山吐月 2010-11-11
  • 打赏
  • 举报
回复
每次总有这样的问题,delegate是最好的办法。原则上线程里面不允许操作控件。
不说了,看代码。
public delegate void SetProgressBar(int value);
public SetProgressBar setProgressbarValue;

//窗体加载中,创建委托
setProgressbarValue = new SetProgressBar(setProgressValue);

//delegate指向的函数
private void setProgressValue(int currentValue)
{
progressBar1.Value = currentValue;
}
线程执行函数:
private void loopData()
{
try
{
for(int i = 0;i<10000;i++)
{
///do something.....
//calculate the percent value of progressbar.
int barValue = (int)(i/10000 * 100);
progressbar.invoke(setProgressbarValue,barvalue);

}
}
catch
{
}
}

大体思路是这样的,现写的语法可能有误。
gggscfaii 2010-11-11
  • 打赏
  • 举报
回复
invokequest//属性
invoke//方法


backgroundworker
Pandoramer 2010-11-11
  • 打赏
  • 举报
回复
当然,慢只是慢在显示上了,你的线程上的任务已经完成了.你可以在线程的循环里加上一个Console.WriteLine(i.ToString())来检查以下
didiaogao 2010-11-11
  • 打赏
  • 举报
回复
如果我不用线程来走WriteDB方法的话。progressBar1.PerformStep();是没问题。。就是加上线程调用。。。。。。 走到这句话的时候就特别慢
SadEmprie 2010-11-11
  • 打赏
  • 举报
回复
.Net2.0以后不允许跨线程访问winform的控件了,所以在WriteDB里直接控制progressbar是不可能的。

具体方法很多,可以用delegate,Google一下能出来很多结果。

另外,读文件的时候一般把progressbar的max设置为文件的size,然后value设置为循环中每次读取的字节数。

这样比较准确。
Pandoramer 2010-11-11
  • 打赏
  • 举报
回复
首先你得代码就不可能被运行.其他线程上怎么能操作progressBar1呢?
另外你还缺少对progressBar1的Step属性的设置.把Step属性设置为1,我这边Step属性默认竟然不是1

至于你说的慢,如果你有很多很多的文件要处理,那么慢是肯定的.因为更新UI是件很费时的操作.相对于你从文件里取三个变量,更新UI要花费更多的时间.甚至多好几倍.譬如说两倍的话,不更新进度条要10秒钟运行完毕,更新进度条后就要用20秒了.
wxm3630478 2010-11-11
  • 打赏
  • 举报
回复

progressBar1.Value = 0;
progressBar1.Maximum = m_numberPlacenames;
for (int i = 0; i < m_numberPlacenames; i++)
{
pName = dataFileReader.ReadString();
pLat = dataFileReader.ReadSingle();
pLon = dataFileReader.ReadSingle();


progressBar1.Value = (i + 1); //应该这么写吧

//progressBar1.PerformStep();
}


//progressBar1.PerformStep(); 用这个方法的话,要设置Step属性,默认是10,自己改一个值能够循环完了,进度也刚好满

慢的原因可能是Step值太小,循环次数太多
苦苦挣扎中 2010-11-11
  • 打赏
  • 举报
回复
可能是进度条设置有问题
freeboy827 2010-11-11
  • 打赏
  • 举报
回复
你的线程方法可以直接操作控件啊
用backgroundworker试试
didiaogao 2010-11-11
  • 打赏
  • 举报
回复
我用委托 试了一下 还是很慢,,我是这么写的看对不对啊。


/// <summary>
/// 读取wwp文件写入数据库文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnWrite_Click(object sender, EventArgs e)
{

System.Threading.Thread thread = new Thread(new ThreadStart(StartWriteDB));
thread.IsBackground = true;
thread.Start();

}

public void StartWriteDB()
{
this.onWriteDBProgress += new writeDBProgress(WriteDB_Progress);
OnWriteDB();
}


// 委托
public delegate void writeDBProgress(long total, long current);
// 事件
public event writeDBProgress onWriteDBProgress;


void WriteDB_Progress(long total, long current)
{
if (this.InvokeRequired)
{
this.Invoke(new writeDBProgress(WriteDB_Progress), new object[] { total, current });
}
else
{
this.progressBar.Maximum = (int)total;
this.progressBar.Value = (int)current;
}
}


在写入文件的方法中把progressBar1.PerformStep();换成了
onWriteDBProgress(placeNamesList.Count, i); // 总条数 和当前执行条数

如下

// 读取操作
private void WriteDB()
{
string wwpFolderPath = @"C:\Documents and Settings\Administrator\桌面\Placenames\乡镇街道\test.wwp";
string[] onePathList = Directory.GetFiles(wwpFolderPath, "*.wwp", SearchOption.TopDirectoryOnly);

BufferedStream dataFileStream = new BufferedStream(File.Open(onePathList[a].ToString(),FileMode.Open,FileAccess.Read, FileShare.Read));
BinaryReader dataFileReader = new BinaryReader(dataFileStream, System.Text.Encoding.GetEncoding("GB2312"));
m_numberPlacenames = dataFileReader.ReadInt32();

for (int i = 0; i < m_numberPlacenames; i++)
{
pName = dataFileReader.ReadString();
pLat = dataFileReader.ReadSingle();
pLon = dataFileReader.ReadSingle();
onWriteDBProgress(placeNamesList.Count, i);
}
}

111,129

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧