C# 线程 dataGridView 和加载

发布于 2024-12-09 01:26:35 字数 3120 浏览 0 评论 0原文

我试图加载一个 dataGridView,这需要一些时间,所以我想出了一个隐藏 datagridview 的想法,并在顶部放置一个图像,上面写着“正在加载...”完成后,图像消失,数据网格重新出现。我尝试使用线程来做到这一点,但没有运气。

有人可以告诉我我是否以正确的方式处理这个问题?

Label loadingText = new Label();
PictureBox loadingPic = new PictureBox(); 

private void TelephoneDirectory_Load(object sender, EventArgs e)
    {
        dataGridView1.Visible = false;

        Thread i = new Thread(LoadImage);
        i.Start();
        Thread t = new Thread(LoadData);
        t.Start();
    }
void LoadImage()
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new MethodInvoker(LoadImage));
        }
        else
        {
            loadingPic.Image = Properties.Resources.ReportServer;
            loadingPic.Location = new Point(0, 0);
            loadingPic.Name = "loadingPic";
            loadingPic.Dock = DockStyle.Fill;
            loadingPic.SizeMode = PictureBoxSizeMode.CenterImage;
            loadingText.Text = "Loading, please wait...";
            loadingText.Name = "loadingText";
            loadingText.TextAlign = ContentAlignment.MiddleCenter;
            loadingText.Size = new Size(this.Size.Width, 30);
            loadingText.Font = new System.Drawing.Font("Segoe UI", 9);
            loadingText.Location = new Point(0, (this.Size.Height / 2 + 10));
            this.Controls.AddRange(new Control[] { loadingPic, loadingText });
            loadingText.BringToFront();
        }
    }
private void LoadData()
    {
        if (dataGridView1.InvokeRequired)
        {
            dataGridView1.Invoke(new MethodInvoker(this.LoadData));
        }
        else
        {

            DirectorySearcher sea = null;
            DirectoryEntry dir = null;
            DirectoryEntry d = null;
            string domainname = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().Name;
            domainname = domainname.Replace(".", ",DC=");
            try
            {

                dir = new DirectoryEntry();
                dir.Path = "LDAP://DC=" + domainname;

                sea = new DirectorySearcher(dir);

                sea.Filter = "(&(objectClass=user)(extensionAttribute1=1)(telephoneNumber=*))";

                sea.PageSize = 2000;
                SearchResultCollection res = sea.FindAll();

                foreach (SearchResult result in res)
                {
                    //DO ALL MY STUFF

                    dataGridView1.Rows.Add(row);
                }

            }
            catch { }
            LoadDataComplete();
        }
    }
void LoadDataComplete()
    {

        PictureBox loadingGraphic = this.Controls["loadingPic"] as PictureBox;

        Label LoadingLabel = this.Controls["loadingText"] as Label;

        DataGridView dataGrid = this.Controls["dataGridView1"] as DataGridView;
        dataGrid.Visible = true;

        LoadingLabel.Visible = false;
        LoadingLabel.Dispose();

        loadingGraphic.Visible = false;
        loadingGraphic.Dispose();

        dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Ascending);
        dataGridView1.ClearSelection();
    }

Im trying to load a dataGridView which takes some time, so ive come up with an idea of hiding the datagridview and put an image over the top which says Loading... when finished, the image goes away and the datagrid reappears. Ive tried to do this using threading but having no luck.

Can somebody tell me if i am approaching this in the right way?

Label loadingText = new Label();
PictureBox loadingPic = new PictureBox(); 

private void TelephoneDirectory_Load(object sender, EventArgs e)
    {
        dataGridView1.Visible = false;

        Thread i = new Thread(LoadImage);
        i.Start();
        Thread t = new Thread(LoadData);
        t.Start();
    }
void LoadImage()
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new MethodInvoker(LoadImage));
        }
        else
        {
            loadingPic.Image = Properties.Resources.ReportServer;
            loadingPic.Location = new Point(0, 0);
            loadingPic.Name = "loadingPic";
            loadingPic.Dock = DockStyle.Fill;
            loadingPic.SizeMode = PictureBoxSizeMode.CenterImage;
            loadingText.Text = "Loading, please wait...";
            loadingText.Name = "loadingText";
            loadingText.TextAlign = ContentAlignment.MiddleCenter;
            loadingText.Size = new Size(this.Size.Width, 30);
            loadingText.Font = new System.Drawing.Font("Segoe UI", 9);
            loadingText.Location = new Point(0, (this.Size.Height / 2 + 10));
            this.Controls.AddRange(new Control[] { loadingPic, loadingText });
            loadingText.BringToFront();
        }
    }
private void LoadData()
    {
        if (dataGridView1.InvokeRequired)
        {
            dataGridView1.Invoke(new MethodInvoker(this.LoadData));
        }
        else
        {

            DirectorySearcher sea = null;
            DirectoryEntry dir = null;
            DirectoryEntry d = null;
            string domainname = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().Name;
            domainname = domainname.Replace(".", ",DC=");
            try
            {

                dir = new DirectoryEntry();
                dir.Path = "LDAP://DC=" + domainname;

                sea = new DirectorySearcher(dir);

                sea.Filter = "(&(objectClass=user)(extensionAttribute1=1)(telephoneNumber=*))";

                sea.PageSize = 2000;
                SearchResultCollection res = sea.FindAll();

                foreach (SearchResult result in res)
                {
                    //DO ALL MY STUFF

                    dataGridView1.Rows.Add(row);
                }

            }
            catch { }
            LoadDataComplete();
        }
    }
void LoadDataComplete()
    {

        PictureBox loadingGraphic = this.Controls["loadingPic"] as PictureBox;

        Label LoadingLabel = this.Controls["loadingText"] as Label;

        DataGridView dataGrid = this.Controls["dataGridView1"] as DataGridView;
        dataGrid.Visible = true;

        LoadingLabel.Visible = false;
        LoadingLabel.Dispose();

        loadingGraphic.Visible = false;
        loadingGraphic.Dispose();

        dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Ascending);
        dataGridView1.ClearSelection();
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

生活了然无味 2024-12-16 01:26:35

为此生成线程可能不是最好的主意,您可以使用 ThreadPool BackgroundWorker

加载图像应该是足够快,您可以同步执行,因此请确保在实际需要之前确实需要在另一个线程上执行一些操作。

问自己这样的问题:如果实际上我的图像比我的数据表加载得晚怎么办? (“但每次我检查时它加载得更快”在谈论线程时不是一个有效的参数)

在方法的开头,您使用 .Invoke 这基本上意味着“等待 UI 线程并调用我的同步编码”,这会轰炸你的整个想法。

尝试这样的事情:

  1. 同步加载图像
  2. 使用 ThreadPool 在其中加载 DataTable,但不使用 .Invoke
  3. 当它加载并且您需要与 UI 交互时 ->然后将代码放入 .Invoke()

伪代码可能如下所示:

private void TelephoneDirectory_Load(object sender, EventArgs e)
{
    dataGridView1.Visible = false;
    LoadImage();

    ThreadPool.QueueUserWorkItem(new WaitCallback(o => LoadData()));
}

void LoadData()
{
    //...Do loading
    //but don't add rows to dataGridView

    if (dataGridView1.InvokeRequired)
    {
        //Invoke only the ui-interaction code
        dataGridView1.Invoke(new MethodInvoker(this.LoadDataComplete));
    }

}

void LoadDataComplete() 
{
    foreach (SearchResult result in res)
    {
        //DO ALL MY STUFF
        //If do all my stuff is compute intensive and doesn't require UI,
        //put it before Invoke() (like here)
        dataGridView1.Rows.Add(row);
    }
    //Rest of code
 }

Spawning threads for this might not be the best idea, you could use ThreadPool or BackgroundWorker

Loading image should be fast enough that you could just do it synchronously, so make sure you actually need to do some operation on the other thread before you actually need it.

Ask yourself questions like: what if actually my image will load later then my dataTable? ("but it loads faster every time I checked" is not an valid argument when talking about threads)

At the beginning of your methods you are using .Invoke which basically means "wait for UI thread and invoke my code on it synchronously" which bombards your whole idea.

Try something like this:

  1. Load image synchronously
  2. Use ThreadPool to load your DataTable in it, but without using .Invoke
  3. When it's loaded and you need to interact with UI -> then put your code in .Invoke()

Pseudocode coud look like this:

private void TelephoneDirectory_Load(object sender, EventArgs e)
{
    dataGridView1.Visible = false;
    LoadImage();

    ThreadPool.QueueUserWorkItem(new WaitCallback(o => LoadData()));
}

void LoadData()
{
    //...Do loading
    //but don't add rows to dataGridView

    if (dataGridView1.InvokeRequired)
    {
        //Invoke only the ui-interaction code
        dataGridView1.Invoke(new MethodInvoker(this.LoadDataComplete));
    }

}

void LoadDataComplete() 
{
    foreach (SearchResult result in res)
    {
        //DO ALL MY STUFF
        //If do all my stuff is compute intensive and doesn't require UI,
        //put it before Invoke() (like here)
        dataGridView1.Rows.Add(row);
    }
    //Rest of code
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文