添加进度条和线程问题

Coordinator
Mar 22, 2012 at 2:32 PM

学长,我想问一下,如果想一边readfile一边进度条往前走的话,我给update进度条和read各开了一个线程,然后根据文件的总大小和当前大小来更新进度条,但是每次一运行,都会说那个bed文件被另一个进程使用,就中断了。我以前没写过线程的东西,不太懂这是哪出的问题。

Coordinator
Mar 22, 2012 at 4:09 PM

读文件过程中文件总大小和当前大小会变化吗?应该可以获得当前文件读取位置,与文件总大小比较可以获得读文件的进度。读文件只占一部分,处理数据也得考虑,可以设置全局变量来记录处理的条数,各处理线程每处理一定条数就更新该变量,同时更新进度条。

这是我的想法

Coordinator
Mar 23, 2012 at 2:25 AM
hanbingjie wrote:

读文件过程中文件总大小和当前大小会变化吗?应该可以获得当前文件读取位置,与文件总大小比较可以获得读文件的进度。读文件只占一部分,处理数据也得考虑,可以设置全局变量来记录处理的条数,各处理线程每处理一定条数就更新该变量,同时更新进度条。

这是我的想法

我同意韩冰杰说的。 韩菁,按道理来说,应该不存在文件的并发访问问题。

“然后根据文件的总大小和当前大小来更新进度条,”--》此处的“大小”是否笔误?应该为“位置”。这个可以从当前的stream.position得到。

按理说不应该出现文件的并发访问问题。你可以咨询一下同学,或者把你的代码贴上来我来参谋一下。

Coordinator
Mar 23, 2012 at 11:12 AM

我在前面把总长度定了,this.Openprogress.Maximum = (new FileInfo(ofd.FileName)).Length;然后开了一个updateopenprogress的线程,在读的时候写的this.displayopeninfo.Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle,new Action<long,long>(UpdateOpenProgress),fileLength,stream.Position);。。。大概就是这样写的~~

Coordinator
Mar 23, 2012 at 2:46 PM
JenniferHan wrote:

我在前面把总长度定了,this.Openprogress.Maximum = (new FileInfo(ofd.FileName)).Length;然后开了一个updateopenprogress的线程,在读的时候写的this.displayopeninfo.Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle,new Action<long,long>(UpdateOpenProgress),fileLength,stream.Position);。。。大概就是这样写的~~

我不太清楚你这些代码哪些是在哪个线程里面跑的。

但是你可以查一下msdn。dispatcher这个东西,别的线程无法访问他这个线程中的资源。所以我怀疑你在dispather里面打开的文件(调用bedfileparser)。

updateprogress 去访问stream,导致出的问题。如果你还需要我的咨询,得把整个代码发过来。光看这点不行。

Coordinator
Mar 24, 2012 at 10:24 AM

http://msdn.microsoft.com/zh-tw/magazine/cc163328.aspx

Coordinator
Mar 24, 2012 at 10:24 AM

http://www.silverlightchina.net/html/study/WPF/2011/0112/4851_2.html

这篇文章讲的不错。下面是我从其中摘抄来的应该是上文中对我们项目最有用的一部分。


程序启动时默认的主线程就是UI线程,它在调用Application.Run(也就是Dispatcher.Run)之后进入了一 个GetMessage的循环中,对Window消息进行响应并构建执行一个个的DispatcherOperation。默认对UI对象的操作都是在这 个主线程中,如果进行耗时很长的操作就会造成UI线程长时间不能继续响应Window消息,造成界面假死等一些的UI响应问题。对这种耗时较长的操作一般 需要工作线程来帮忙,操作结束后再通过Dispatcher把结果Invoke到UI线程,如:
TextBlock textBlock = new TextBlock() { Text = "1" }; 
Thread thread = new Thread(new ThreadStart(() => 
    { 
        //做一些耗时操作,这里用线程休眠10秒来模拟 
         Thread.Sleep(TimeSpan.FromSeconds(10));
        textBlock.Dispatcher.Invoke(new Action(() => 
            { 
                textBlock.Text = "2"; 
            })); 
    })); thread.Start();

当然,除了新建工作线程,也可以使用BackgroundWorker或者线程池中线程来进行耗时操作,操作结束后需要调用UI对象 Dispatcher的Invoke或者BeginInvoke方法来操作UI,否则会抛出InvalidOperationException来提示不 可跨线程访问UI对象。

Coordinator
Mar 26, 2012 at 8:00 AM

hi 韩菁,我看 韩冰杰已经用了我提到的方法来异步操作了。

你可以和他咨询一下,而且在他的基础上改一下就是你需要完成的任务了。

Coordinator
Mar 26, 2012 at 10:08 AM

恩恩。。。好~~我现在那个也已经跑起来了。但是时间上要比以前的慢了,我再去问问他。