【问题标题】:Get current value in a for loop在 for 循环中获取当前值
【发布时间】:2013-09-06 01:44:08
【问题描述】:

我有几个嵌套的 for 循环,我想知道是否可以在它处理数据的同时获取数据,所以我可以将它作为加载栏显示在屏幕上。

这是一个例子:

double currentData;
double endData = 50 * 50 * 50;

for(int i = 0; i < 50; i++)
{
  for(int e = 0; e < 50; e++)
  {
    for(int a = 0; a < 50; a++)
    {
      currentData = a * e * i;
    }
  }  
}

label1.Text = "Loading: " + Convert.ToString(100/endData * currentData) + "%.";

如果我没记错的话,for 循环会使程序“冻结”直到它完成,所以这可能就是这段代码不起作用的原因。有什么建议吗?

谢谢

【问题讨论】:

  • for(int a : 0; a &lt; 50; a++) 是错字吗?
  • 糟糕,改了,谢谢
  • 您可以将label1.Text = 行放在循环中,并在其后直接调用Application.DoEvents。或者查找 BackgroundWorker 并使用它在后台线程中完成工作。

标签: c# winforms for-loop loading


【解决方案1】:

如果你使用WinForms,你可以使用后台工作者来执行循环:

//declare in form
var bw = new BackgroundWorker();

//in constructor or load write this
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler(bwDoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bwProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwCompleted);

private void bwDoWork(object sender, DoWorkEventArgs e)
{
    var worker = sender as BackgroundWorker;
    for(int i = 0; i < 50; i++)
    {
        for(int e = 0; e < 50; e++)
        {
            for(int a : 0; a < 50; a++)
            {
                worker.ReportProgress(a * e * i);
            }
        }  
    }
}

private void bwProgressChanged(object sender, ProgressChangedEventArgs e)
{
    var pp=e.ProgressPercentage; //now set the progress here
}

private void bwCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //set the progress to 100% etc.
}

然后正如@paqogomez 所指出的,您需要调用工作人员来运行,可能是在某些按钮单击等上。

//may be in private void button_click(object sender, EventArgs e)
if (!bw.IsBusy)
{
    bw.RunWorkerAsync();
}

您可以获取有关 BackgroundWorker herehere 的更多信息。

【讨论】:

  • 那里还需要一个 RunWorkerAsync。
  • 好吧,你比我想承认的时间要长。 ;)
  • 挑剔:bw.IsBusy != true?为什么不只是!bw.IsBusy
  • @Blorgbeard 如果它在我的任何项目中,我会结帐并编辑此行。但只是为了完成答案。把这个从 MSDN 链接。更多信息的第一个链接。我现在已经编辑过了。
【解决方案2】:

如果我没记错的话,for 循环会使程序“冻结”直到它完成,所以这可能就是这段代码不起作用的原因。

您是绝对正确的:如果您在 UI 线程上运行循环,则 UI 在循环完成之前不会更新,因此这种方法不可行。

有什么建议吗?

您需要在后台线程中完成这项工作,并随时更新progressBar。您将无法直接从不同的线程设置值,因此您需要使用委托和特殊的调度机制。这里是an answer that shows how this is done in WPF and Windows Forms

【讨论】:

    【解决方案3】:

    您的假设是正确的,如果您想看到它发生变化,请尝试在您的 for 循环中更新 label1.Text

    【讨论】:

    • 除非你也调用Application.DoEvents,否则你实际上什么都看不到。
    • 哦。这很有意义......谢谢!编辑:Application.DoEvents?
    • 好吧,不是那么正确,程序不会死机,它只是在更新标签之前完成循环
    • @NickPeelman 通常在执行for 循环时,这就是程序正在做的所有事情:它甚至没有做诸如重新绘制屏幕之类的事情。 Application.DoEvents 告诉它需要几毫秒来处理移动/调整大小/重绘/等工作。
    • @SimonRapilly 他在引号中写了“冻结”,我认为他并不是字面意思。
    猜你喜欢
    • 2023-01-23
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2020-12-18
    • 2020-11-23
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多