【问题标题】:How can I load data for multiple TabPages concurrently in a WinForms application如何在 WinForms 应用程序中同时加载多个 TabPages 的数据
【发布时间】:2022-01-06 11:09:16
【问题描述】:

我有一个带有包含多个 TabPage 的 TabControl 的 Windows 窗体应用程序。每个 TabPage 包含许多控件,其数据通过 Web api 从数据库中读取。我希望能够显示至少一个 TabPage 及其数据,而其余的 TabPages 正在加载。我知道我无法在线程中加载控件,因此我需要一种方法在后台同时为每个 TabPage 进行数据检索,然后使用检索到的数据填充每个 TabPage 上的控件。所以我的问题是:这样做的理想方法是什么?我想优先考虑性能。我还希望在页面仍在加载的每个 TabPage 标题上都有一些视觉指示。想法?想法?直接回答?

【问题讨论】:

  • 您可以同时使用任务和线程。并行加载数据,只需在加载数据完成后(合法地)访问 UI 控件。

标签: multithreading winforms backgroundworker tabpage


【解决方案1】:

您可以在并行线程中加载数据,并且在加载数据完成后,然后通过调用Invoke 方法更新UI(合法)以防止跨线程异常。您还可以使用并行任务加载数据,并在每个任务完成时更新数据。

在以下示例中,数据在并行线程中加载,一旦每个线程/任务完成,UI 就会更新。

示例 1 - 使用 Task 将数据并行加载到 UI 中

private NorthwindClient client = new NorthwindClient();
private void Form1_Load(object sender, EventArgs e)
{
    LoadCategories();
    LoadProducts();
}
private void LoadProducts()
{
    productsTabPage.Text = "Loading ...";
    var products = client.GetProductsAsync().GetAwaiter();
    products.OnCompleted(() =>
    {
        productsDataGridView.DataSource = products.GetResult();
        productsTabPage.Text = "Products";
    });
}
private void LoadCategories()
{
    categoriesTabPage.Text = "Loading ...";
    var categories = client.GetCategoriesAsync().GetAwaiter();
    categories.OnCompleted(() =>
    {
        categoriesDataGridView.DataSource = categories.GetResult();
        categoriesTabPage.Text = "Categories";
    });
}

示例 2 - 使用 Thread 将数据并行加载到 UI 中

private NorthwindClient client = new NorthwindClient();
private void Form1_Load(object sender, EventArgs e)
{
    LoadCategories();
    LoadProducts();
}
private void LoadProducts()
{
    productsTabPage.Text = "Loading ...";
    new Thread(() =>
    {
        var products = client.GetProducts();
        Invoke(new Action(() =>
        {
            productsDataGridView.DataSource = products;
            productsTabPage.Text = "Products";
        }));
    }).Start();
}
private void LoadCategories()
{
    categoriesTabPage.Text = "Loading ...";
    new Thread(() =>
    {
        var categories = client.GetCategories();
        Invoke(new Action(() =>
        {
            categoriesDataGridView.DataSource = categories;
            categoriesTabPage.Text = "Categories";
        }));
    }).Start();
}

NorthwindClient - 两个示例的通用代码

以上两个示例都依赖以下代码来加载数据:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
public class NorthwindClient
{
    static HttpClient client;
    static NorthwindClient()
    {
        client = new HttpClient();
        client.BaseAddress = new Uri("https://northwind.vercel.app/api/");
    }
    public async Task<IEnumerable<Category>> GetCategoriesAsync()
    {
        var response = await client.GetStringAsync("categories");
        return JsonConvert.DeserializeObject<IEnumerable<Category>>(response);
    }
    public async Task<IEnumerable<Product>> GetProductsAsync()
    {
        var response = await client.GetStringAsync("products");
        return JsonConvert.DeserializeObject<IEnumerable<Product>>(response);
    }
    public IEnumerable<Category> GetCategories()
    {
        var response = client.GetStringAsync("categories").Result;
        return JsonConvert.DeserializeObject<IEnumerable<Category>>(response);
    }
    public IEnumerable<Product> GetProducts()
    {
        var response = client.GetStringAsync("products").Result;
        return JsonConvert.DeserializeObject<IEnumerable<Product>>(response);
    }
}
public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}
public class Product
{
    public int Id { get; set; }
    public int SupplierId { get; set; }
    public int categoryId { get; set; }
    public string QuantityPerUnit { get; set; }
    public decimal UnitPrice { get; set; }
    public int UnitsInStock { get; set; }
    public int UnitsOnOrder { get; set; }
    public int ReorderLevel { get; set; }
    public bool Discontinued { get; set; }
    public string Name { get; set; }
}

【讨论】:

  • 在应用解决方案时如果您有任何疑问或问题,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-17
  • 1970-01-01
  • 1970-01-01
  • 2018-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多