从后台工作程序更新GUI [英] Updating the GUI from background worker

查看:90
本文介绍了从后台工作程序更新GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题的名称是:"从后台工作程序更新GUI ",但正确的名称世界是:"从后台工作程序更新GUI或报告多变量(其他比整数)"

The name of the question is: "Updating the GUI from background worker", but the correct name world be: "Updating the GUI from background worker OR reporting multiple-variables (other than an integer) from background worker"

请让我解释一下我的情况.在一个程序中,我有一个后台工作人员来分析信息.作为分析的结果-表单GUI元素应填充必要的数据.在GUI中,我想更新

Please let me explain my situation. In a program I have a background worker which analyses the information.As the result of this analysis - form GUI elements should be populated with necessary data. In GUI I would like to update

  • 2个datagridviews
  • 1个列表框
  • 5个标签

据我了解-我只能通过后台工作人员的ReportProgress()方法以本机方式报告1 int.

所以问题是-如何通过ReportProgress()传递List<>(+其他一些变量:stringint)?基本上-我想用信息更新GUI,但是"1整数"就不行了.因此,应该可以通过ReportProgress()传递多个变量,或者我可以从BackgroundWorker内部使用Invoke本身来更新GUI..我个人不喜欢Invoke方法...您有何看法?

So the question is - how can I pass a List<> ( + some other variables: string, int) via ReportProgress()? Basically - i want to update the GUI with the information but "1 integer" just won't do.. So either it should be possible to pass multiple variables via an ReportProgress() OR i can use an Invoke from inside the BackgroundWorker itself to update the GUI.. Personally I don't like the Invoke approach... What's your opinion?

这是我的代码(请参见注释):

Here is my code (see the comments):

   private void button9_Click(object sender, EventArgs e) // start BW
    {
        bw.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
        bw.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;

        bw.RunWorkerAsync(10);
    }

    private void button10_Click(object sender, EventArgs e) // cancel BW
    {
        bw.CancelAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        int count = (int)e.Argument;
        for (int i = 1; i <= count; i++)
        {
            if (bw.CancellationPending)
            {
                e.Cancel = true;
                break;
            }

            List<List<string>> list_result = new List<List<string>>();
            list_result = Proccess();

            bw.ReportProgress(list_result.Count()); // right now I can only return a single INT

            /////////// UPDATE GUI //////////////
            // change datagridview 1 based on "list_result" values
            // change datagridview 2
            // change listbox
            // change label 1
            // change label ..          

            Thread.Sleep(20000);
        }

        MessageBox.Show("Complete!");
        e.Result = sum;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        prog_count++;
        listBox1.Items.Add("Count: (" + prog_count.ToString() + "/20). Found: " + e.ProgressPercentage.ToString() + ".");
    }

推荐答案

调用ReportProgress时有一个UserState参数.

var list_result = new List<List<string>>();

new backgroundWorker1.ReportProgress(0, list_result);

参数类型是object,因此您必须将其强制转换回所需的类型:

The parameter type is an object so you'll have to cast it back to the type you need:

void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    var userState = (List<List<string>>)e.UserState;
}   

棘手的问题是,如何确定要传回List,列表列表,单个字符串,数字等.您必须测试ProgressChanged事件.

The tricky issue with this is, how do you determine whether you're passing back a List, or a list of lists, or a single string, number, etc. You'll have to test for each possibility in the ProgressChanged event.

void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    var myList = e.UserState as List<List<string>>;
    if (myList != null)
    {
        // use list
        return;
    }

    int myNumber;
    if (Int32.TryParse(e.UserState.ToString(), out myNumber))
    {
        // use number
        return;
    }

    var myString = e.UserState.ToString();
    // use string
}

或者,您可以创建一个包含所需所有值的类(或使用

Alternatively, you could create a class that holds all the values you need (or use Tuple), run everything in the background to populate that class, then pass that to the RunWorkerCompleted event, and update your UI all at once from there.

这篇关于从后台工作程序更新GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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