如何防止程序在存在加载栏时不响应



我正在创建一个程序,该程序可以在启动时从文件中读取大量数据。

我尝试了一个进度条,它将显示加载进度,希望它能停止无响应,但它中途冻结并更新屏幕上的标签以解决问题。

//This will be 'private void Form1_Shown(object sender, EventArgs e)'
private void loadingBarToolStripMenuItem_Click(object sender, EventArgs e)
{
progressBar1.Show();
for (int i = 0; i < 100; i++)
{
progressBar1.Value = i;
System.Threading.Thread.Sleep(50);
//StartRespondingAgain();
}
progressBar1.Hide();
}

此问题不是加载栏,而是您在 GUI 线程上运行了长期操作。

应该调用事件,完成其工作并尽快返回。只能同时运行一段代码,并且当此事件运行时,不能执行其他事件 - 甚至不能执行更改的绘制。

您需要添加某种形式的多任务处理。此操作不会从大量线程/任务(例如每个文件一个(中受益,但至少可以将长时间运行的循环移动到单独的任务中。BackgroundWorkers、Threads 和 Async/Await 只是 3 种方法。我个人认为BackgroundWorker 很好 - 但有点过时 - "训练轮子"来学习多任务处理,特别是多线程。我什至得到了一些示例代码:

#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
if (!bgwPrim.IsBusy)
{
//Prepare ProgressBar and Textbox
int temp = (int)nudPrim.Value;
pgbPrim.Maximum = temp;
tbPrim.Text = "";
//Start processing
bgwPrim.RunWorkerAsync(temp);
}
}
private void btnPrimCancel_Click(object sender, EventArgs e)
{
if (bgwPrim.IsBusy)
{
bgwPrim.CancelAsync();
}
}
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
int highestToCheck = (int)e.Argument;
//Get a reference to the BackgroundWorker running this code
//for Progress Updates and Cancelation checking
BackgroundWorker thisWorker = (BackgroundWorker)sender;
//Create the list that stores the results and is returned by DoWork
List<int> Primes = new List<int>();

//Check all uneven numbers between 1 and whatever the user choose as upper limit
for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
{
//Report progress
thisWorker.ReportProgress(PrimeCandidate);
bool isNoPrime = false;
//Check if the Cancelation was requested during the last loop
if (thisWorker.CancellationPending)
{
//Tell the Backgroundworker you are canceling and exit the for-loop
e.Cancel = true;
break;
}
//Determin if this is a Prime Number
for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
{
if (PrimeCandidate % j == 0)
isNoPrime = true;
}
if (!isNoPrime)
Primes.Add(PrimeCandidate);
}
//Tell the progress bar you are finished
thisWorker.ReportProgress(highestToCheck);
//Save Return Value
e.Result = Primes.ToArray();
}
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbPrim.Value = e.ProgressPercentage;
}
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pgbPrim.Value = pgbPrim.Maximum;
this.Refresh();
if (!e.Cancelled && e.Error == null)
{
//Show the Result
int[] Primes = (int[])e.Result;
StringBuilder sbOutput = new StringBuilder();
foreach (int Prim in Primes)
{
sbOutput.Append(Prim.ToString() + Environment.NewLine);
}
tbPrim.Text = sbOutput.ToString();
}
else 
{
tbPrim.Text = "Operation canceled by user or Exception";
}
}
#endregion

但这是一个你可以选择毒药的领域。

最新更新