c# - 如何正确更新 DataGridView,这样 GUI 就不会卡住

标签 c# .net datagridview freeze

我有一个 backgroundworker,它进行一些计算并将进度结果报告为字符串。此字符串需要插入到 dataGridView 中。但是在插入值时,GUI 会卡住。

private void bckgrSorter_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i=0; i<1000; i++)
    {
        // doing some calculations
        bckgrSorter.ReportProgress(i, someString);
    }
}    

 private void bckgrSorter_ProgressChanged(object sender, ProgressChangedEventArgs e)
 {
     string results = (string)e.UserState;
     dataGridView1.Rows.Add(results);
 }

因此,即使我在后台线程上进行了所有繁重的计算,GUI 仍然卡住,因为 DataGridView。

编辑代码:

private void bckgrSorter_DoWork(object sender, DoWorkEventArgs e)
    {
        string[] folders = // some folders to get File List from

        bckgrFileScanner.RunWorkerAsync(folders);            
    }

private void bckgrFileScanner_DoWork(object sender, DoWorkEventArgs e)
    {
        string[] folders = (string[])e.Argument;
        foreach (string f in folders)
        {
            GetFileList(ref scannedFiles, f, bckgrFileScanner);
            bckgrFileScanner.ReportProgress(1);
        }
    }

public void GetFileList(ref List<FileInfo> fList, string fPath, BackgroundWorker scanner)
        {
            DirectoryInfo di = new DirectoryInfo(fPath);
            FileInfo[] fi = di.GetFiles();

            foreach (FileInfo fiTemp in fi)
            {
                //ar ~$ saakas nevajadzīgie temp faili, tos izlaižam
                if (fiTemp.Name.StartsWith("~$") == false)
                {
                    fList.Add(fiTemp);
                    scanner.ReportProgress(0, fiTemp.Name);
                }
            }
            DirectoryInfo[] dFolders = di.GetDirectories();

            //katrai apakšmapei rekursīvi izsaucam šo funkciju
            foreach (DirectoryInfo d in dFolders)
            {
                GetFileList(ref fList, d.FullName, scanner);
            }
        }

private void bckgrFileScanner_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (e.ProgressPercentage == 0)
        {
            filesDataGrid.Rows.Add(e.UserState);
        }

        else progressBar1.PerformStep();
    }

最佳答案

在我看来,您需要对工作线程的结果进行批处理。也许您可以使 ProgressChanged 事件返回进度结果的集合或其他内容?或者最多每半秒使用最新数据触发一次事件。我怀疑问题是您只是想过快地添加数据。您需要在每个单元中完成更少的工作单元和更多的工作(一次添加很多行)。

巴巴尔是对的。像这样的东西可能会做你想做的事(我没有试过编译它):

    public void GetFileList(ref List<FileInfo> fList, string fPath, BackgroundWorker scanner)
    {
        DirectoryInfo di = new DirectoryInfo(fPath);
        FileInfo[] fi = di.GetFiles();

        List<string> progressData = new List<string>();

        foreach (FileInfo fiTemp in fi)
        {
            //ar ~$ saakas nevajadzigie temp faili, tos izlaižam
            if (fiTemp.Name.StartsWith("~$") == false)
            {
                fList.Add(fiTemp);
                progressData.Add(fiTemp.Name);
                if (progressData.Count > 50){
                    scanner.ReportProgress(0, progressData.ToArray());
                    progressData.Clear();//You've just copied the data to an array and sent it to the GUI, clear the list and start counting up again
                }
            }
        }

        if (progressData.Count > 0){
            scanner.ReportProgress(0, progressData.ToArray());
        }

        DirectoryInfo[] dFolders = di.GetDirectories();

        //katrai apakšmapei rekursivi izsaucam šo funkciju
        foreach (DirectoryInfo d in dFolders)
        {
            GetFileList(ref fList, d.FullName, scanner);
        }
    }

这不是一个很好的解决方案,但它是一个开始......

您还需要在回调中将 e.UserState 转换为字符串数组...

关于c# - 如何正确更新 DataGridView,这样 GUI 就不会卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5702090/

相关文章:

c# - Paypal C# merchant-sdk-dotnet

C# GUI,必须显示一个巨大的表格并使其可排序

c# - 如何在 DataGridView 中获取选定的数据行?

c# - ASP.NET Core Response.End()?

c# - WebBrowser 控件调整大小

c# - 通过使用 moq 模拟另一个方法来测试一个方法是否被调用

C# 和 .NET 的关系

c# - 将复选框动态添加到不显示文本的 CheckBoxList

c# - 在 ASP.Net Web API Controller 中如何找到用户名?

c# - Datagridview 显示类名而不是属性