简体   繁体   English

加载表单时的进度条

[英]Progress bar while form is loading

I have created a lot of UserControls which have heavy background images. 我创建了许多具有沉重背景图像的UserControls。 I placed them on a form. 我将它们放在表格上。 Everything works nice after form's loading has finished. 表单加载完成后,一切正常。 Problem is - it takes 10 seconds before form appears on screen. 问题是-表格出现在屏幕上需要10秒钟。

I searched through the internet and found a solution - showing a temporary form saying "Please wait...". 我在互联网上搜索并找到了解决方案-显示一个临时表格,上面写着“请稍候...”。

Now I am wondering is there a possibility to replace "Please wait" message with ProgressBar . 现在,我想知道是否可以用ProgressBar替换“请稍候”消息。 Not marquee one. 不选一。 The one which would actually show form's loading progress. 实际上显示表单加载进度的那个。

I examined code and it turned out that heavy part is located in InitializeComponent . 我检查了代码,结果发现很大一部分位于InitializeComponent InitializeComponent is generated automatically so I should not edit manually, right? InitializeComponent是自动生成的,所以我不应该手动编辑,对吗? I tried to move InitializeComponent to separate thread. 我试图将InitializeComponent移到单独的线程。 It turned out to be a bad idea because controls should not be created in different threads. 事实证明这是一个坏主意,因为不应在不同的线程中创建控件。

You should check out background worker. 您应该签出后台工作人员。

BackgroundWorker 的BackgroundWorker

BackgroundWorker Tutorial BackgroundWorker教程

https://www.dotnetperls.com/progressbar https://www.dotnetperls.com/progressbar

there are methods u can use for progress bar. 有一些方法可以用于进度条。 I think it might help. 我认为这可能会有所帮助。 Good luck. 祝好运。

As you have already experienced you cannot run the InitializeComponent method in another thread. 如您所料,您不能在另一个线程中运行InitializeComponent方法。 But you can delay some initialization. 但是您可以延迟一些初始化。 If you are sure that the image loading is so slow (are they downloaded from a remote location?), then remove the image initialization from the designer (eg. by nullifying the Image properties) and load them only after the form is shown: 如果您确定图像加载太慢(它们是从远程位置下载的吗?),请从设计器中删除图像初始化(例如,通过使Image属性无效)并仅在显示表单后才加载它们:

public Form1()
{
    InitializeComponent();
}

private async void Form1_Load(object sender, EventArgs e)
{
    progressBar1.Visible = true;
    progressBar1.Value = 0;
    await LoadImages();
    progressBar1.Visible = false;
}

// Just represents a simple source-target mapping so you can associate the loaded images with their targets
// Here I use a path-control mapping just for the case of the example
private ICollection<KeyValuePair<string, Control>> GetImageMapping()
{
    var basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonPictures), "Sample Pictures");
    var mapping = new Dictionary<string, Control>
    {
        [Path.Combine(basePath, "Tulips.jpg")] = this, // form1
        [Path.Combine(basePath, "Chrysanthemum.jpg")] = button1,
        // etc, eg. myUserControl1...
    };

    return mapping;
}

private async Task LoadImages()
{
    var mapping = GetImageMapping();
    progressBar1.Maximum = mapping.Count;
    foreach (var item in mapping)
    {
        var image = await LoadImage(item.Key);
        item.Value.BackgroundImage = image;
        progressBar1.Value++;
    }
}

private async Task<Image> LoadImage(string imagePath)
{
    // This makes 1s delay for each image to imitate slow loading. You do NOT need this line actually.
    await Task.Delay(1000);

    // Only this part will be executed in another thread:
    return await Task.Run<Image>(() =>
    {
        // or download it, load from a stream, resource, whatever...
        var result = Image.FromFile(imagePath);
        return result;
    });
}

Please note that the form can be closed before the loading progress finishes so you might need some extra checks, too. 请注意,可以在完成加载进度之前关闭表单,因此您可能还需要进行一些额外的检查。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM