DataGridView窗体在后台工作完成后显示为空 [英] DataGridView form shows up empty after background worker finish

查看:165
本文介绍了DataGridView窗体在后台工作完成后显示为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

需要求你帮忙,因为我很挣扎太久了。已经经历了许多教程,但无法想像出来...

Need to ask you for help as I'm struggling with this for too long now. Have gone over many tutorials but can't figure it out yet...

在这个项目的第一阶段,我开发了一个控制台程序,可以向Web服务器发出请求,处理数据并更新MS Access DB。我现在出现的问题是,在完成所有处理之后,我需要将结果显示在一个winform中,让客户看到它,而且在应用程序打开的时候,更多的过程应该是一遍又一遍的。

In a first stage of this proyect I developed a console program that makes requests to a web server, processes the data and updates a MS Access DB. My problem arise now that after doing all that processing, I need to show the result inside a winform for the clients to see it, and even more the process should be going over and over again while the app is opened.

所以到目前为止,我已经做了一个创建一个winform来运行控制台程序作为后台工作人员,结果应该随着程序的持续运行而显示和更新。为了简单起见,我正在替换所有重要的处理,只是一个填充一个HashTables列表的循环,它返回到winform显示:

So what I've done so far is a creating a winform that runs the console program as a background worker and the results should be shown and updated as the program keeps running. For simplicity, I'm replacing all the heavy processing for just a loop that fills in a List of HashTables, which is returned to the winform to be displayed:

    namespace TheNameSpace
{
    class aldeloUpdater
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new GuiForm());
        }

        public List<Hashtable> oldMain()
        {
            List<Hashtable> products = new List<Hashtable>();

            try
            {
                Hashtable product1 = new Hashtable();
                Hashtable product2 = new Hashtable();
                Hashtable product3 = new Hashtable();

                product1.Add("productName", "Empanada de Pollo");
                product1.Add("userName", "Fabio Roman");
                product1.Add("dateAndTime", "2016-08-11 15:50:52");
                product1.Add("domiciliosOrderId", "1932211-20160811155052");
                products.Add(product1);

                product2.Add("productName", "Empanada de Carne");
                ...
                products.Add(product2);

                product3.Add("productName", "Empanada Mixta");
                ...
                products.Add(product3);

                Console.WriteLine("A message for debugging.");
                Console.ReadLine();

                return products;
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception details: " + e.ToString());
                Console.ReadLine();
                return products;
            }
        }

        // More Methods and classes
}

现在,对于winform,我已经得到了:

Now as for the winform I've got this:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;

namespace TheNameSpace
{
    public partial class GuiForm : Form
    {
        public List<Hashtable> dataGridViewProducts;

        public GuiForm()
        {
            InitializeComponent();
            InitializeBackgroundWorker();
            backgroundWorker.RunWorkerAsync(); // Initialize the whole process.
        }

        // Set up the BackgroundWorker object by 
        // attaching event handlers. 
        private void InitializeBackgroundWorker()
        {
            backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            backgroundWorker.RunWorkerCompleted +=
                new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerComplet);
        }


        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void GuiForm_Load(object sender, EventArgs e)
        {
            int index = 0;
            if (dataGridViewProducts != null && !dataGridViewProducts.Any())
            {
                foreach (Hashtable product in dataGridViewProducts)
                {
                    dataGridView1.ReadOnly = false;
                    dataGridView1.Rows.Add();
                    dataGridView1.Rows[index].Cells[0].Value = product["productName"];
                    dataGridView1.Rows[index].Cells[1].Value = product["userName"];
                    dataGridView1.Rows[index].Cells[2].Value = product["dateAndTime"];
                    dataGridView1.Rows[index].Cells[3].Value = product["domiciliosOrderId"];
                    index++;
                }
                return;
            } 
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Logic for a delete-button
        }

        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            aldeloUpdater aldeloThread = new aldeloUpdater();
            this.dataGridViewProducts = aldeloThread.oldMain();

            //this.GuiForm_Load(); // ¿Do I need to make this call? ¿How to?
            this.Show();
        }

        private void backgroundWorker_RunWorkerComplet(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else
            {
                MessageBox.Show(e.Result.ToString());
            }
        }
    }
}

一直期待这个结果:

但是相反,我得到这个:

But instead I'm getting this:

I知道我在做错事,但是我不知道那是什么,怎么做好,我是PHP后端的开发者,这是我第一个C#程序。请帮助。

I know I'm doing something wrong, but I just don't know what is that and how to do it well, I'm PHP back-end dev and this is my very first C# program. Please help.

推荐答案

没有一个好的最小,完整的和可验证的代码示例,无法确定什么是最好的解决方案。但是,根据上面发布的代码,我可以提供一些建议:

Without a good Minimal, Complete, and Verifiable code example, it's impossible to know for sure what would the best solution. But based on the code you posted above, I can provide some suggestions:


  1. 似乎没有任何需要 oldMain()成为一个实例方法。你可以使它 public static List< Hashtable> oldMain(),然后将其称为 aldeloUpdater.oldMain()。更好的是,为方法创建一个单独的类,而不是将其放在主要的程序类中。

  2. 你写了一个评论阅读我需要打电话吗?如何?。我会回答这个是的,你需要打这个电话。由于该方法必须访问UI对象,特别是您的 dataGridView1 对象,您应该在$ code> RunWorkerCompleted 事件处理程序中调用它:

  1. There doesn't appear to be any need for oldMain() to be an instance method. You can make it public static List<Hashtable> oldMain() and then call it as aldeloUpdater.oldMain(). Even better, create a separate class for the method, rather than putting it in what would otherwise be your main Program class.
  2. You wrote a comment reading "Do I need to make this call? How to?". I would answer this as "yes, you need to make this call." Since the method has to access the UI objects, specifically your dataGridView1 object, you should call it in the RunWorkerCompleted event handler:

private void backgroundWorker_RunWorkerComplet(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        MessageBox.Show(e.Error.Message);
    }
    else
    {
        MessageBox.Show(e.Result.ToString());
        GuiForm_Load(sender, e);
    }
}


尽管如此,你实际上并没有在你的 GuiForm_Load中使用发件人 e 方法,所以在我看来你可以省略那些。

Though, you don't actually use the sender and e parameters in your GuiForm_Load() method, so it seems to me you could just omit those.


  1. 已经通过 Main()方法显示,通过将其传递给 Application.Run()方法。所以不需要在 DoWork 事件处理程序中调用 this.Show()。无论如何,这是调用 Show()的错误地方,因为您在此时执行错误的线程。你应该删除那个电话。

  1. The form is already shown by the Main() method, by passing it to the Application.Run() method. So there shouldn't be any need to call this.Show() in the DoWork event handler. That's the wrong place to call Show() anyway, since you're executing in the wrong thread at that point. You should just remove that call.

这篇关于DataGridView窗体在后台工作完成后显示为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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