c# - 如何同时构建字符串?

标签 c# async-await task

在下面给出的 MWE(最小工作示例)中,我配置了

  • Simulator.CpuBoundOperation("red", 150)); 在线程池线程中以红色字体旋转 150 次。

  • Simulator.CpuBoundOperation("green", 550); 以绿色字体旋转 550 次。

我想要获得一个 HTML 输出,其中包含一串线程 id 和交替的红绿数字,因为它们是同时运行的。

不幸的是,输出显示了不需要的结果,其中首先打印所有绿色数字,然后打印所有红色数字。我尝试增加迭代次数,但效果不佳。

如何解决这个问题?

MWE

using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

static class Simulator
{
    private static readonly StringBuilder sb = new StringBuilder();

    static Simulator()
    {
        string begin = "<!DOCTYPE html><html><body style='width:500px;background-color:black;font-size:20pt'><p>";
        sb.Append(begin);
    }

    public static void CpuBoundOperation(string color, int n = 50)
    {
        for (long i = 0; i < n; i++)
            sb.Append($"<span style='color:{color}'>{Thread.CurrentThread.ManagedThreadId} </span>");
        // a white space before </span> is important
    }

    public static new string ToString()
    {
        sb.Append("</p></body></html>");
        return sb.ToString();
    }
}

class Test
{

    static async Task Main(string[] args)
    {
        await Work();
        File.WriteAllText("output.html", Simulator.ToString());
    }

    static async Task Work()
    {
        Task t = Task.Run(() => Simulator.CpuBoundOperation("red", 150));
        Simulator.CpuBoundOperation("green", 550);
        await t;
        Simulator.CpuBoundOperation("blue");
    }
}

enter image description here

最佳答案

在主线程完成绿色数字之前,您的操作(显然)没有花费足够的时间来运行后台线程。

坦率地说,你很幸运,所发生的只是后台任务直到主线程等待才开始。 StringBuilder 不是线程安全的,因此如果您并发执行,您就会损坏 StringBuilder,充其量会产生完全错误的输出,最坏的情况下会导致程序崩溃。

尚不清楚为什么要交错文本,但如果这是必需的,则应该在单个线程中执行此操作。无论如何,没有足够的工作来证明并发性的合理性,至少在示例程序中是这样。如果您确实想保证并发性,则必须为主线程添加逻辑,以便在后台线程开始工作之前不会开始工作,但这有点反模式,因为它违背了并发性的主要目的:最大化吞吐量计算。

关于c# - 如何同时构建字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46987121/

相关文章:

javascript - 在 foreach 循环中的 Promise.all 之后修改数组

java - 如何在java中创建使用进度监视器的任务?

spring - 在 Spring 中超时 Controller /方法的执行时间

c# - 未关闭的sql连接

c# - 安排 C# 应用程序

javascript - 使用Async/Await正确尝试…捕获语法

c# - Task.Factory.FromAsync 是否触发创建的任务?

task - 是否有您认为非常重要的编程任务,以至于您总是深思熟虑、缓慢地完成它们?

c# - 在 MVC 4 脚本部分初始化 jQuery DataTable 时隐藏表数据的最佳方法是什么

C#定期从串口读取新行