使用c#代码逐一更新Label控件

本文关键字:更新 Label 控件 代码 使用 | 更新日期: 2023-09-27 17:52:41

我有一个windows窗体的标签控件,我有一个代码如下所示:-

我在代码中添加了一些额外的行,我做了进一步的工作。但是,Label控件仍然没有一个一个地更新。

 void function1()
 {
     FOLDER1 = DRIVE + @":'Foldername1";
     LOGFILE1 = FOLDER1 + @"'Foldername2";

     Process msbuild;
     msbuild = new Process();
     DEVENV = Environment.GetEnvironmentVariable("VS100COMNTOOLS") + @"..'IDE'devenv.exe";
     var list = System.IO.Directory.GetFiles(LOGFILE1);
     foreach (var item in list)
     {
         System.IO.File.Delete(item);
     }

     // Creation of array of string to Build Projects before Building Up.      
     array[0] = @"'make'versionupdate'versionupdate_vs2010.sln   /build  Release";
    for (int k = 0; k < array.Length; k++)
    {
         msbuild.StartInfo.UseShellExecute = false;
         msbuild.StartInfo.CreateNoWindow = true;
         msbuild.StartInfo.Arguments = FOLDER1 + array[k] + @" /out " + LOGFILE1;
         msbuild.StartInfo.FileName = DEVENV;
         msbuild.Start();
         msbuild.WaitForExit();
         UpdateProgress();
    }
}
void UpdateProgress()
{
    if (InvokeRequired)
    {
        MethodInvoker method = new MethodInvoker(UpdateProgress);
        Invoke(method);
        return;
    }
    if(checkbox1.Checked)
    {
        for (int k = 0; k < array.Length; k++)
        {
            this.lbl_CurrentProject.Text = "Current Project: " + @"  " + array[k];
            progressBar1.Value = int.Parse(((k * 100) / array.Length).ToString());
            progressBar1.CreateGraphics().DrawString(((k * 100) / array.Length).ToString() + "%", new Font("Arial", (float)10.25, FontStyle.Bold), Brushes.Black, new PointF(progressBar1.Width / 2 - 10, progressBar1.Height / 2 - 7));
            System.Threading.Thread.Sleep(100);
            progressBar1.PerformStep();
            progressBar1.Refresh();
        }
    }
}
     private void bn_Start_Click(object sender, EventArgs e)
    {
        if (checkbox1.Checked)
        {
            if (string.IsNullOrEmpty(cmb_drive.Text))
            {
                DRIVE = "-";
            }
            else
            {
                DRIVE = cmb_drive.GetItemText(cmb_drive.SelectedItem);
            }
            if (thread1 != null)
            {
                thread1.Abort();
            }

            thread1 = new Thread(function1);
            thread1.Start();
          }
        }

这里发生的事情是标签控件没有一个一个地更新。当项目在字符串数组中构建时,我想更新标签控件,而不是一次全部更新。

请帮我处理一下上面的代码。谢谢。

使用c#代码逐一更新Label控件

你需要使用BackgroundWorker,因为你不能从另一个线程更新控件。

正确的方法-是使用BackgroundWorker为您的目的。另一种方法(几乎正确的方法)-使用Control.Invoke方法。还有另一种几乎正确的方法——使用SynchronizationContext。

E。委托更新进度条根据你最后的评论,你可以使用下面的delegatemmethod

void UpdateProgress()
{
    if (InvokeRequired)
    {
        MethodInvoker method = new MethodInvoker(UpdateProgress);
        Invoke(method);
        return;
    }

        if(checkbox1.Checked)
        {
            for (int k = 0; k < array.Length; k++)
            {


this.Invoke((MethodInvoker)delegate {
                this.lbl_CurrentProject.Text = "Current Project: " + @"  " + array[k];
                progressBar1.Value = int.Parse(((k * 100) / array.Length).ToString());
                progressBar1.CreateGraphics().DrawString(((k * 100) / array.Length).ToString() + "%", new Font("Arial", (float)10.25, FontStyle.Bold), Brushes.Black, new PointF(progressBar1.Width / 2 - 10, progressBar1.Height / 2 - 7));
                System.Threading.Thread.Sleep(100);
                progressBar1.PerformStep();
                progressBar1.Refresh();
});
            }
}

像往常一样(其他人已经提到过),您不能在gui线程中执行任何长时间运行的工作,否则它将冻结并且用户无法再交互。BackgroundWorker的存在就是为了这个目的。它在另一个线程中运行负载,并且允许在gui线程运行时(通过ReportProgress())或完成时(通过RunWorkerCompleted回调)轻松返回到gui线程以更新gui。

我刚刚写了一个简单的例子,它展示了使用后台工作器的概念(可能还有一种或其他技术来改进你的代码):

public Form1()
{
    InitializeComponent();
    // ToDo: Refactor this into a method that will be called
    //       on some kind of event (eg. button click).
    var rootFolder = @"D:'Root";
    var outputFolder = Path.Combine(rootFolder, @"'Bin'Release");
    var solutions = GetAvailableSolutions(rootFolder);
    var arguments = solutions.Select(solution => String.Join(" ", solution, "/build Release", "/out " + outputFolder));
    var processes = arguments.Select(CreateMsBuildProcess);
    var worker = new BackgroundWorker();
    worker.DoWork += OnWorkerDoWork;
    worker.ProgressChanged += OnWorkerProgressChanged;
    worker.RunWorkerCompleted += OnWorkerRunWorkerCompleted;
    worker.WorkerSupportsCancellation = true;
    worker.WorkerReportsProgress = true;
    // ToDo: Disable start button
    ClearFolder(outputFolder);
    worker.RunWorkerAsync(processes);
}
private IEnumerable<String> GetAvailableSolutions(String rootFolder)
{
    // ToDo: Change retrieving of .sln files to any logic you alike.
    return Directory.EnumerateFiles(rootFolder, "*.sln", SearchOption.AllDirectories);
}
private void OnWorkerDoWork(object sender, DoWorkEventArgs e)
{
    var index = 0;
    var worker = (BackgroundWorker)sender;
    // ToDo: Give in a self created class instead of process to easier
    //       access the needed text for ReportProgress().
    var processes = (IEnumerable<Process>)e.Argument;
    foreach (var process in processes)
    {
        if (worker.CancellationPending)
            break;
        worker.ReportProgress(index, process.StartInfo.Arguments);
        process.Start();
        process.WaitForExit();
    }
}
private void OnWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
    var text = (String)e.UserState;
    // ToDo: Update label and progress bar.
    // Eg. label.Text = text; progressBar.PerformStep(); or progressBar.Value = e.ProgressPercentage;
}
private void OnWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // ToDo: Enable Start button.
    // Eg. buttonStart.Enabled = true;
}
private static void ClearFolder(String folder)
{
    if (Directory.Exists(folder))
        Directory.Delete(folder, true);
    Directory.CreateDirectory(folder);
}
private static Process CreateMsBuildProcess(String arguments)
{
    var devEnvPath = Path.Combine(Environment.GetEnvironmentVariable("VS100COMNTOOLS"), @"..'IDE'devenv.exe");
    var startInfo = new ProcessStartInfo
    {
        UseShellExecute = false,
        CreateNoWindow = true,
        Arguments = arguments,
        FileName = devEnvPath
    };
    var process = new Process { StartInfo = startInfo };
    return process;
}

由于评论而更新:我做错了什么?

差不多什么都有。似乎您没有花任何时间使用我提供的代码示例,因为我展示了如何使用BackgroundWorker,而您使用了Thread(错误的方式)。看来你很幸运地挑了我的好日子。我将给出表单(或控件)构造函数中需要提供的代码以及在按钮click事件中需要调用的代码:

private BackgroundWorker _Worker;
public Form1()
{
    InitializeComponent();
    // Maybe other stuff you initialize within the ctor...
    _Worker = new BackgroundWorker();
    _Worker.DoWork += OnWorkerDoWork;
    _Worker.ProgressChanged += OnWorkerProgressChanged;
    _Worker.RunWorkerCompleted += OnWorkerRunWorkerCompleted;
    _Worker.WorkerSupportsCancellation = true;
    _Worker.WorkerReportsProgress = true;
}
private void bn_Start_Click(object sender, EventArgs e)
{
    string drive;
    if (checkbox1.Checked)
    {
        if (string.IsNullOrEmpty(cmb_drive.Text))
        {
            drive = "-";
            return;
        }
        else
        {
            drive = cmb_drive.GetItemText(cmb_drive.SelectedItem);
        }
        if (_Worker.IsBusy)
        {
            _Worker.CancelAsync();
            // ToDo: Update gui by disable buttons, etc and show that cancelation is pending.
            //       The enabling of the buttons, etc should happen in OnWorkerRunWorkerCompleted()
            return;
        }
        var rootFolder = Path.Combine(drive + ":", "Foldername1");
        var outputFolder = Path.Combine(rootFolder, @"Foldername2");
        var solutions = GetAvailableSolutions(rootFolder);
        var arguments = solutions.Select(solution => String.Join(" ", solution, "/build Release", "/out " + outputFolder));
        var processes = arguments.Select(CreateMsBuildProcess);
        // ToDo: Disable start button and update gui that processing has started.
        // btn_Start.Enabled = false;
        ClearFolder(outputFolder);
        _Worker.RunWorkerAsync(processes);

    }
}