如何避免在循环中冻结GUI?

问题描述 投票:0回答:1

即使我的进程在另一个线程中运行,如果我运行太多数据,我的GUI也会冻结。实际上,即使GUI被锁定,该线程也将一直运行直到完成。所以我认为我的代码出了点问题

double MeasNoAvgwrapper()
{
    double temp = 0D;
    double[] tempList = new double [MeasNoAvg];

    for(int t = 0; t < MeasNoAvg; t++)
    {
        tempList[t] = AveragePixeLink2();
    }

    temp = tempList.Average();

    return temp;
}

有人看到它有问题吗?

c# loops user-interface memory freeze
1个回答
0
投票

使用WinForms,您可以使用它来允许Application调度事件并刷新GUI,同时禁用表单以禁止用户交互并在需要时更改鼠标光标:

Cursor = Cursors.WaitCursor;  // for UX
Enabled = false;              // for UX
try
{
  for ( int t = 0; t < MeasNoAvg; t++ )
  {
    tempList[t] = AveragePixeLink2();
    Refresh();
    Application.DoEvents();   // for UI
  }
  temp = tempList.Average();
}
finally
{
  Enabled = true;
  Cursor = Cursors.Default;
}

您还可以添加默认情况下禁用的取消按钮,以允许使用条件变量来停止该过程。

在这种情况下,您可以通过使用SetFormEnabled()方法来禁用所有您希望用户不允许其一一进行交互的控件(禁用面板将禁用所有内部控件)。>>

private bool CancelRequired;
SetFormEnabled(false);
Cursor = Cursors.WaitCursor;
CancelRequired = false;
ButtonCancel.Enabled = true;
try
{
  for ( int t = 0; t < MeasNoAvg; t++ )
  {
    if ( CancelRequired ) break;
    tempList[t] = AveragePixeLink2();
    Refresh();
    Application.DoEvents();
  }
  temp = tempList.Average();
}
finally
{
  CancelRequired = false;
  ButtonCancel.Enabled = false;
  Cursor = Cursors.Default;
  SetFormEnabled(true);
}
private void ButtonCancel_Click(object sender, EventArgs e)
{
  CancelRequired = true;
}

如果该过程需要时间,则可以在表单上或具有TopMost true的初始框中使用进度条:

SplashForm.cs或当前表单

public void InitProgress(int stepCount, int stepIncrement)
{
  progressBar.Minimum = 0;
  progressBar.Maximum = stepCount;
  progressBar.Value = 0;
  progressBar.Step = stepIncrement;
}

void DoProgress()
{
  progressBar.PerformStep();
  progressBar.Refresh();
  Application.DoEvents();  // Instead of in a loop
}

来电者表格

SetFormEnabled(false);
var splash = new SplashForm();
splash.InitProgress(MeasNoAvg, 1);
splash.Show();
CancelRequired = false;
ButtonCancel.Enabled = true;
Cursor = Cursors.WaitCursor;
try
{
  for ( int t = 0; t < MeasNoAvg; t++ )
  {
    if ( CancelRequired ) break;
    tempList[t] = AveragePixeLink2();
    Refresh();
    splash.DoProgress();
  }
  temp = tempList.Average();
}
finally
{
  CancelRequired = false;
  ButtonCancel.Enabled = false;
  Cursor = Cursors.Default;
  splash.Close();
  SetFormEnabled(true);
}

如果进度条位于主窗体中,请不要使用飞溅,最后将进度条的值设置为0。

© www.soinside.com 2019 - 2024. All rights reserved.