简体   繁体   English

进度条工作但标签没有更新

[英]Progress bar working but label is not updating

I have a library with an Interface.我有一个带接口的库。

Public Interface Progress
{
    int ProgressValue{get;set;},
    string ProgressText{get;set;},
}

Library has a method Create (dummy code):库有一个方法创建(虚拟代码):

Public Class TestLibrary
{

    Progress _progress;

    Public void Create()
    {
        foreach(var n in TestList)
        {
            // Do Something
            _progress.ProgressValue = GetIndex(n);
            _progress.ProgressText = "Updating..." + n;
        }
    }
}

I have a project that references this library and calls Create method.我有一个引用这个库并调用 Create 方法的项目。 It even Implements Interface Progress.它甚至实现了接口进程。

Public Class TestProject : Progress
{
    public int ProgressValue
    {
        get{return progressBar1.Value;}
        set{progressBar1.Value = value;}
    }

    public int ProgressText
    {
        get{return label1.Text;}
        set{label1.Text = value;}
    }
}

Now when I run the application, Progress Bar behaves properly and shows the progress correctly, but the Text of label1 does not change at all.现在,当我运行应用程序时,Progress Bar 行为正常并正确显示进度,但 label1 的 Text 根本没有改变。 But it do change in the end of for loop and shows the last item in loop.但它确实在 for 循环结束时发生了变化,并显示了循环中的最后一项。 Can anyone help me out in this?任何人都可以帮我解决这个问题吗?

Note: All these codes are written directly without testing as I don't have my application now with me.注意:所有这些代码都是直接编写的,没有经过测试,因为我现在没有我的应用程序。 Sorry for any syntax errors.抱歉任何语法错误。

It sounds like all your work is being done on the UI thread.听起来您的所有工作都在 UI 线程上完成。 Don't do that.不要那样做。

Instead, run the loop itself in a background thread, and use Control.Invoke or Control.BeginInvoke (probably in the Progress implementation) to marshal a call across to the UI thread just to update the UI.相反,在后台线程中运行循环本身,并使用Control.InvokeControl.BeginInvoke (可能在Progress实现中)将调用编组到 UI 线程,只是为了更新 UI。 This will leave your UI responsive (and able to update labels etc) while it's still processing.这将使您的 UI 在它仍在处理时保持响应(并能够更新标签等)。

Used a Label instead of ProgressBar .使用Label instead of ProgressBar You can try this code [ using BackGroundWorker ] -你可以试试这个代码 [ using BackGroundWorker ] -

using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form3 : Form
    {
        private BackgroundWorker _worker;
        BusinessClass _biz = new BusinessClass();
        public Form3()
        {
            InitializeComponent();
            InitWorker();
        }

        private void InitWorker()
        {
            if (_worker != null)
            {
                _worker.Dispose();
            }

            _worker = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };
            _worker.DoWork += DoWork;
            _worker.RunWorkerCompleted += RunWorkerCompleted;
            _worker.ProgressChanged += ProgressChanged;
            _worker.RunWorkerAsync();
        }


        void DoWork(object sender, DoWorkEventArgs e)
        {
            int highestPercentageReached = 0;
            if (_worker.CancellationPending)
            {
                e.Cancel = true;
            }
            else
            {
                double i = 0.0d;
                int junk = 0;
                for (i = 0; i <= 199990000; i++)
                {
                    int result = _biz.MyFunction(junk);
                    junk++;

                    // Report progress as a percentage of the total task.
                    var percentComplete = (int)(i / 199990000 * 100);
                    if (percentComplete > highestPercentageReached)
                    {
                        highestPercentageReached = percentComplete;
                        // note I can pass the business class result also and display the same in the LABEL  
                        _worker.ReportProgress(percentComplete, result);
                        _worker.CancelAsync();
                    }
                }

            }
        }

        void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                // Display some message to the user that task has been
                // cancelled
            }
            else if (e.Error != null)
            {
                // Do something with the error
            }
        }

        void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text =  string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage);
        }
    }

    public class BusinessClass
    {
        public int MyFunction(int input)
        {
            return input+10;
        }
    }
}

Posted the same a few days ago here几天前在这里发布了相同的内容

The code you posted uses one thread.您发布的代码使用一个线程。 That means every operation is excuted in sequence right after the previous one finished.这意味着在前一个操作完成后,每个操作都会按顺序执行。 Since you can update GUI elements right away, I suppose the code to be run from main thread (aka "GUI thread").由于您可以立即更新 GUI 元素,我认为代码将从主线程(又名“GUI 线程”)运行。 Blocking the GUI thread results in the GUI ("Graphical User Interface") not updating until there is some idle time for it.阻塞 GUI 线程会导致 GUI(“图形用户界面”)直到有一些空闲时间才更新。

Use following example to refresh your label every iteration so that it updates your UI.使用以下示例在每次迭代时刷新您的标签,以便它更新您的 UI。

label1.Text = i.ToString();
label1.Refresh();

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

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