C#的winform的BackgroundWorker [英] C# winform backgroundworker

查看:120
本文介绍了C#的winform的BackgroundWorker的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在为自己工作一个家庭项目。
该程序是使用winforms在C#中编写的。

I am currently working on a home project for myself. The program is written in C# using winforms.

我目前遇到的问题如下:

The problem I'm currently experiencing is as followed:

我在mainform中有一个listview,名为lvwGames
当我运行程序没有调试,它运行正常。
然而,当我开始调试,我得到一个错误。这与背景工作者线程有关。

I have a listview in my mainform called lvwGames When I run the program without debugging, it runs fine. However when I start with a debug, I get an error. This has something to do with the background worker thread.

允许我发布一些代码来帮助我。

Allow me to post some code to assist me.

    private void MainViewLoad(object sender, EventArgs e)
    {
        RefreshGamesListView();
    }

这里没有什么特别的。
我调用RefreshGamesListView()的原因是因为我必须在几次刷新。

Nothing special here. The reason I am calling RefreshGamesListView() is because I have to refresh on several occasions.

被调用的方法看起来像这样。

The method being called looks like this.

    public void RefreshGamesListView()
    {
        pbRefreshGamesList.Value = 0;
        bgwRefreshList.RunWorkerAsync();
    }

所以当方法被调用时,后台worker被调用并运行dowork方法。
这一个很大。

So when the method is called, the background worker is called and runs the dowork method. This one is quite big.

    private void BgwRefreshListDoWork(object sender, DoWorkEventArgs e)
    {
        List<Game> games = _mainController.RetrieveAllGames();

        int count = 1;
        foreach (Game game in games)
        {
            string id = game.id.ToString();
            var li = new ListViewItem(id, 0);
            li.SubItems.Add(game.title);
            li.SubItems.Add(game.Genre.name);
            li.SubItems.Add(game.Publisher.name);
            li.SubItems.Add(game.Platform.name);
            li.SubItems.Add(game.CompletionType.name);
            li.SubItems.Add(game.gameNotice);
            lvwGames.Items.Add(li);

            double dIndex = (double)(count);
            double dTotal = (double)games.Count;
            double dProgressPercentage = (dIndex / dTotal);
            int iProgressPercentage = (int)(dProgressPercentage * 100);

            count++;
            bgwRefreshList.ReportProgress(iProgressPercentage);
        }
    }



当我在调试中运行代码时,是在lvwGames.Items.Add(li);
它给我以下错误:

When i run the code in debug, when the code is on lvwGames.Items.Add(li); It gives me the following error:

Cross-thread operation not valid: Control 'lvwGames' accessed from a thread other than the thread it was created on.

我完全没有线索。
我认为它是代码特定的。但它也意味着我不能得到后台工作人员完全,特别是什么时候正确使用它。

I have absolutely no clue why. I think it is code specific. But it can also mean I don't get the background worker completely, and specifically when to use it properly.

我使用它的原因是因为我从数据库加载了一个大的大列表,我想在UI加载列表时保持响应,

The reason I'm using it is because I'm loading a large large list from the database, I want to keep responsiveness in the UI when the list is loaded, and inform the users how far it is, using a progress bar.

如果任何代码缺失,或者你实际上明白为什么会发生,请告诉我为什么在这种情况下它导致错误。你不需要为我修复它。我只是想知道为什么它是造成的。

If any code is missing, or you actually understand why this is happening PLEASE explain me why in this case its causing the error. You don't need to fix it for me. I just want to know WHY it's caused.

感谢您花时间阅读这篇文章。我希望能够很快继续使用调试器。 :)

Thanks for taking the time to read this post. I hope to be able to continue using the debugger soon. :)

推荐答案

这是因为您尝试访问UI控件( lvwGames )从后台线程。使它工作的方式需要您将信息编组回主UI线程并更新控件:

This is because you're attempting to access a UI control (lvwGames) from a background thread. The way to make it work requires you to marshal the information back to the main UI thread and update the control from there:

private void BgwRefreshListDoWork(object sender, DoWorkEventArgs e)
{
    List<Game> games = _mainController.RetrieveAllGames();

    int count = 1;
    foreach (Game game in games)
    {
        string id = game.id.ToString();
        var li = new ListViewItem(id, 0);
        li.SubItems.Add(game.title);
        li.SubItems.Add(game.Genre.name);
        li.SubItems.Add(game.Publisher.name);
        li.SubItems.Add(game.Platform.name);
        li.SubItems.Add(game.CompletionType.name);
        li.SubItems.Add(game.gameNotice);

        // This is the new line you need:
        lvwGames.Invoke(new MethodInvoker(delegate { lvwGames.Items.Add(item) }));

        double dIndex = (double)(count);
        double dTotal = (double)games.Count;
        double dProgressPercentage = (dIndex / dTotal);
        int iProgressPercentage = (int)(dProgressPercentage * 100);

        count++;
        bgwRefreshList.ReportProgress(iProgressPercentage);
    }
}

通常你会检查 InvokeRequired 属性,在其他答案中提到的,但真的没有必要,如果你总是从后台线程调用它。您的 DoWork 方法将总是需要调用invoke,因此您可以直接进行编写。

Normally you would check the InvokeRequired property first as mentioned in other answers, but there is really no need if you are always calling it from the background thread. Your DoWork method will always require an invoke call, so you might as well just go ahead and write it like that.

这篇关于C#的winform的BackgroundWorker的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆