我正在运行此代码并冻结我的程序一段时间来填充文本框。有没有办法更快地做到这一点?或者如果不能通过在后台运行来加快速度,那么我可以继续使用该程序吗?
var numbers = "0123456789";
var q = numbers.Select(x => x.ToString());
int size = 4;
for (int i = 0; i < size - 1; i++)
q = q.SelectMany(x => numbers, (x, y) => x + y);
foreach (var item in q)
{
//Console.WriteLine(item);
textBox.Text += item + Environment.NewLine;
}
答案 0 :(得分:4)
使用后台工作程序无法解决根本问题;你没有正确填写文本框。
通过在循环中直接使用+=
字符串运算符,您使用的是Schlemiel the Painter's algorithm,效率非常低。
您可以使用StringBuilder解决此问题,并仅在文本框中显示最终结果:
StringBuilder sb = new StringBuilder();
foreach (var item in q)
{
sb.Append(item + Environment.NewLine);
}
textBox.Text += sb.ToString();
迭代你的10k数字最多不应超过几毫秒。
答案 1 :(得分:1)
主要问题似乎是将字符串直接连接到控件,控件会在其Text
属性的每次修改时自行刷新。试试这个版本:
var result = string.Empty;
foreach (var item in q)
{
result += item + Environment.NewLine;
}
textBox.Text = result;
你也可以使用StringBuilder
,但在我的机器上差异毫无意义(编辑:显然不是,详情如下)。当然,您通常应该使用BackgroundWorker
进行繁重的计算。这是现代机器的边界情况恕我直言。
作为Pierre-Luc Pineault下his answer讨论的后续行动,我做了一些测量,结果就是这样:
StringBuilder average: 0,9336, stddev: 0,591938375170962 [ms]
String average: 61,9763, stddev: 7,17896498877082 [ms]
所以是的,即使在这种情况下你也应该使用StringBuilder
:
var result = new StringBuilder();
foreach (var item in q)
{
result.Append(item + Environment.NewLine);
}
textBox.Text = result.ToString();
以下是我用来进行测量的代码:
class Test
{
private static Stopwatch sw = new Stopwatch();
public static int st()
{
var numbers = "0123456789";
var q = numbers.Select(x => x.ToString());
int size = 4;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < size - 1; i++)
q = q.SelectMany(x => numbers, (x, y) => x + y);
String s = "";
foreach (var item in q)
s += item;
return s.Length;
}
public static int sb()
{
var numbers = "0123456789";
var q = numbers.Select(x => x.ToString());
int size = 4;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < size - 1; i++)
q = q.SelectMany(x => numbers, (x, y) => x + y);
StringBuilder sb = new StringBuilder();
foreach (var item in q)
sb.Append(item);
return sb.ToString().Length;
}
static void Main()
{
int n = 100000;
List<long> sbSamples = new List<long>(n);
List<long> stSamples = new List<long>(n);
for (int i = 0; i < n; ++i)
{
sw.Reset();
sw.Start();
sb();
sw.Stop();
sbSamples.Add(sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
st();
sw.Stop();
stSamples.Add(sw.ElapsedMilliseconds);
}
double sbAv = 1.0 * sbSamples.Sum() / sbSamples.Count;
double stAv = 1.0 * stSamples.Sum() / sbSamples.Count;
double sbStdDev = Math.Sqrt(sbSamples.Select(x
=> (x - sbAv) * (x - sbAv)).Sum() / sbSamples.Count);
double stStdDev = Math.Sqrt(stSamples.Select(x
=> (x - stAv) * (x - stAv)).Sum() / stSamples.Count);
Console.WriteLine(
"StringBuilder average: " + sbAv + ", stddev: " + sbStdDev);
Console.WriteLine(
"String average: " + stAv + ", stddev: " + stStdDev);
Console.ReadKey();
}
}