如题,软件是一个读取文件的,里面有大量数据,文件数目量也比较大.将文件读取到datatable,然后绑定gridview进行显示.使用的backgroundWorker.
调试的时候怎么都正常.没有意外.
问题就在按ctrl+f5或者直接运行bin下面exe的时候,在文件数少的情况下正常,但是当读取大量文件时,到最后完成的时候,整个软件就死掉了(应该是在完成backgroundWorker_DoWork后几秒,因为读取文件是执行完了的,然后会死在调用完成函数backgroundWorker_RunWorkerCompleted的途中,注意是途中...但是这个函数并不执行什么复杂的,只是改变一下label,如果不使用RunWorkerCompleted函数,则会在完成后几秒软件莫名死掉)...代码没有什么特别的//按钮调用
        private void Load_Button_Click(object sender, EventArgs e)
        {
            if (Directory.Exists(textBox_FilePath.Text) && (textBox_FilePath.Text != null))
            {
                backgroundWorker_load.RunWorkerAsync();
            }
            else
            {
                MessageBox.Show("Wrong folder path?");
            }
        }//DoWork函数
        private void backgroundWorker_load_DoWork(object sender, DoWorkEventArgs e)
        {
            buttonenable(false);
            load185.initdt();
            string[] files = new string[256];
            int count = 0;
            PublicLoadFunc.GetFileList(textBox_FilePath.Text.Trim(), files, ref count);
            if (files[0] == null)
            {
                MessageBox.Show("No file found.");
                return;
            }
            for (int i = 0; i < count; i++)
            {
                backgroundWorker_load.ReportProgress((i * 100 + 50) / count,i.ToString()+"/"+count.ToString()+ "  Loading " + files[i].ToString().Trim() + ".");
                NewDelegate startLoad = new NewDelegate (load185.LoadOneFile);
                startLoad.Invoke(files[i].ToString().Trim(), i);
                //load185.LoadOneFile(files[i].ToString().Trim(), i);//这里用不用委托都一样
                backgroundWorker_load.ReportProgress(((i + 1) * 100) / count, (i+1).ToString() + "/" + count.ToString() + "  Loading " + files[i].ToString().Trim() + " completed.");
                Application.DoEvents();
            }
        }完全想不明白了,也不知道怎么调试,弄了一天了哎,伤感...求高手指教

解决方案 »

  1.   

    在WinForm中经常遇到一些费时的操作界面,比如统计某个磁盘分区的文件夹或者文件数目,如果分区很大或者文件过多的话,处理不好就会造成“假死”的情况,或者报“线程间操作无效”的异常,为了解决这个问题,可以使用委托来处理,在.net2.0中还可以用BackgroundWorker类。BackgroundWorker类是.net 2.0里新增加的一个类,对于需要长时间操作而不需要用户长时间等待的情况可以使用这个类。 注意确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。
      

  2.   

    首先从代码看,似乎lz对于BackgroundWorker理解的不太完全正确,DoWork里面还在访问界面的控件是根本不对的。至于假死,那原因可多了去了,不调试是没办法的。至于调试,WinDbg + SOS最实际了,可惜BW多线程还搞不清楚的估计没那么容易上手。付费找个高手去你那里帮你看看好了。反正基本就是你代码的问题。人家Visual Studio编译一大堆文件都你这么假死的。
      

  3.   

    肯定是代码问题 不是逻辑问题 就是组件的使用问题!  根据LZ贴出来的代码 应该是BackgroundWorker的使用问题    就如2楼说的一样:
     "注意确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信"  实在不行 你就用new Thread + delgate试试!就算操作20个G我也遇到过问题!
      

  4.   

    肯定是代码的问题  一是逻辑问题 二是使用组件的方法问题  根据LZ贴出来的代码看来 就是BackgroundWorker的使用问题了  就如二楼所说的:
    "注意确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信"  注意访问用户界面的方式!如果不行的话就用New Thread() + Delgate来做吧! 可能有助于你理解BackgroundWorker
      

  5.   

    调试的前提是你复现一个bug,然后借助调试器查看器一层层嵌套代码和入口变量。发布一个程序,基于测试而不是基于调试。进行足够的测试之后才能发布程序。调试对于发布软件毫无意义。
      

  6.   


    谢谢~确实理解很浅,现在的代码看上去只有buttonenable和Application.DoEvents()跟界面有关,但是之前我根本就没加这2条在DoWork里面,我也都删掉试过,只留下逻辑相关的,还是会死,我明天试一下!非常感谢!
      

  7.   

    换thread+delegate做了
    应该不是我backgroundworker的问题,虽然给出来的代码有些不对,但是出问题之前不是这么用的.怎么改都不行换之后发现是gridview的问题,还是老问题下拉条假死(这是公认的vs2005的bug么),但是好在程序没死,Application.DoEvents()也没用.
    我想可能就是因为这个gridview的假死,导致backgroundworker出问题.
    等等看有没人能帮忙解释或者解决下?
    晚上结贴~谢谢大家!
      

  8.   

    不是gridview的假死,只是滚动条无法使用...
      

  9.   

    楼主你应该透过现象看本质,这个问题的根源不在于数据量大就会死,而在于怎么样在界面中显示巨大的数据量。只要优化了显示数据的方式,这个“死”的问题就自然解决了。我以前做过一个CCProxy日志分析软件,允许用户选择一个时间段内的日志进行过滤,那个数据量有多大几乎是没办法想的,如果按你的方法……所以,你得在列表上面做文章。我当时用的是ListView控件,其实用DataGridView的原理也差不多了,就是使用控件的虚拟模式。对于ListView控件来说,设置它的VirtualMode为true,再处理几个关键的事件就可以了,具体的用法三言两语说不清,顺手G了点资料,希望对你有用:
    http://msdn.microsoft.com/zh-cn/library/system.windows.forms.listview.virtualmode.aspx
    http://www.cnblogs.com/hcfalan/archive/2008/07/08/1238493.html
    http://www.cnblogs.com/easydata/archive/2008/07/02/1234161.html
      

  10.   

    问题解决了
    因为我datatable的处理是在子线程里的,但是我为了能即时显示数据,程序一开始就绑定了datatable为gridview的数据源,而子线程的开始并没有使用this.invoke+委托而是直接用的委托开始的线程,这样也算导致了跨线程更新界面,之前的backgroundworker肯定也是因为这个数据源跨线程问题导致gridview滚动条假死进而整个程序死掉.
    不知道我的分析有没有错误.
    如果没错,就顺便提醒一下之前遇到gridview滚动条假死无效的朋友们,应该都是和我类似的问题了,就是要用this.invoke+委托来处理gridview的数据源.
      

  11.   

    我也遇到这个问题了,也是完全不知道要怎么调试f5完全正常;Ctrl+f5就不正常了,