C#代码执行需要很长时间

时间:2014-01-22 17:35:17

标签: c#

我正在运行此代码并冻结我的程序一段时间来填充文本框。有没有办法更快地做到这一点?或者如果不能通过在后台运行来加快速度,那么我可以继续使用该程序吗?

        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;
        }

2 个答案:

答案 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 Pineaulthis 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();
    }
}