我exprementing打印出整數的所有可能的乘法在等於數組大小的數組的應用程序:與後臺工作人員報告LINQ查詢的進度,如何?
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
int progress = 0;
int toCheck = int.Parse(textBox2.Text); //Number to check for
int[] array = new int[toCheck];
//Fill the array
for (int i = 0; i < toCheck; i++)
{
array[i] = i;
bgw.ReportProgress(progress);
progress += 1;
}
var result =
from i1 in array
from i2 in array
where i1 * i2 == toCheck
let square = i1 * i2
select new { i1, i2, square }; //how to report progress here?
foreach (var res in result)
{
textBox1.Text += res.i1 + " * " + res.i2 + " = " + res.square + Environment.NewLine;
bgw.ReportProgress(progress);
progress += 1;
}
}
LINQ查詢本身是非常耗費時間特別是如果一個大數目應檢查。有沒有辦法報告linq查詢的進度?或者我應該離開linq並做這種老派模式?
更新 這是我的整個代碼。進度欄在半滿後不會填滿。前半部分是數組創建時,第二部分是代碼嘗試執行linq查詢時(這就是爲什麼我認爲報告應該在linq查詢中完成!)原諒我的愚蠢!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace BGWorkerTest
{
public partial class Form1 : Form
{
private PerformanceCounter cpuCounter;
private PerformanceCounter ramCounter;
string[] diagnosticInfo = new string[2] { string.Empty, string.Empty };
int toCheck = 0;
StringBuilder sb;
public Form1()
{
InitializeComponent();
//Diagnostics
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
ramCounter = new PerformanceCounter("Memory", "Available KBytes");
}
private string[] GetDiagnostics()
{
diagnosticInfo[0] = string.Format("{0:0.##}", cpuCounter.NextValue()) + "%";
diagnosticInfo[1] = ramCounter.NextValue() + "MB";
return diagnosticInfo;
}
private void timerStStr_Tick(object sender, EventArgs e)
{
string[] temp = new string[2] { "", ""};
temp = GetDiagnostics();
ststrLabelCpu.Text = temp[0];
ststrLabelMem.Text = temp[1];
}
private void button1_Click(object sender, EventArgs e)
{
ststrProgBar.Minimum = 0;
ststrProgBar.Maximum = 0;
toCheck = int.Parse(textBox2.Text);
ststrProgBar.Minimum = 0;
ststrProgBar.Maximum = toCheck * 2;
ststrProgBar.Step = 1;
//Starts the backgroundworker process asynchronously
bgw.RunWorkerAsync();
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
int progress = 0;
int[] array = new int[toCheck + 1];
for (int i = 0; i < toCheck + 1; i++)
{
array[i] = i;
bgw.ReportProgress(progress);
progress += 1;
}
var result =
from i1 in array
from i2 in array
where i1 * i2 == toCheck
let square = i1 * i2
select new { i1, i2, square };
sb = new StringBuilder();
foreach (var res in result)
{
sb.AppendLine(res.i1 + " * " + res.i2 + " = " + res.square);
bgw.ReportProgress(progress);
progress += 1;
Application.DoEvents();
}
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ststrProgBar.PerformStep();
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("Operation Cancelled");
}
else
{
MessageBox.Show("Operation Completed");
textBox1.Text = sb.ToString();
}
}
}
}
每當你找到一場比賽,你都會報告進度;每次發現不匹配時,你想報告進度嗎? – Rawling 2011-12-19 11:18:54
我不明白,我在哪裏報道了我寫的linq查詢中匹配的發現?! for循環中的ReportProgress()只是報告數組正在被創建,因爲更大的整數需要相當長的時間才能填充數組。對於文本框每次都要報告一行。我沒有在實際的linq查詢中報告。 – 2011-12-19 11:25:00
Linq是懶惰的;它沒有找到每一個匹配,然後將它們傳遞給你的foreach循環,但是一旦找到每個匹配,就將這些值逐個傳遞給你的foreach循環。因此,在foreach循環中,您的ReportProgress實質上應該是在每次找到匹配時進行報告。如果沒有發生 - 例如你會得到大量的等待,然後是很多快速報告 - 我不知道爲什麼。 – Rawling 2011-12-19 11:28:54