在 C# 中以随机顺序线程 运行

Threads running in random order in C#

我认为标题不言自明。只是我有一些 运行 随机顺序而不是我计划的顺序的线程。 这是示例代码:

    event strHandler strChanged;
    delegate void strHandler(string str);

    public Form1()
    {
        InitializeComponent();

        strChanged += new strHandler(updatestr);
    }

    public void updatestr(string str)
    {
        Thread th = new Thread(new ParameterizedThreadStart(updatethr));
        th.IsBackground = true;
        th.Start(str); 
    }

    object obj = new object();

    private void updatethr(object str)
    {
        lock (obj)
        {
            SystemUtilities.SetControlPropertyThreadSafe(textBox1, "Text", (string)str);
            Thread.Sleep(1000);
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        this.Text = write();
    }

    private string write()
    {
        string res = "";
        strChanged(res);
        for (int i = 0; i <= 5; i++)
        {
            res += i.ToString();
            strChanged(res);
        }
        return res;
    }

注意:SystemUtilities.SetControlPropertyThreadSafe(textBox1, "Text", (string)str) 是将textBox1.Text设置为str的函数(用于避免跨线程异常)。 当您按下按钮 1 时,this.Text 将立即设置为 write() 函数的结果(“012345”)。 返回的字符串是 res,它是在 write() 内部构建的,从一个空字符串开始,并迭代地附加从 0 到 5 的数字。 创建字符串并为每个添加到 res 的数字时,将引发事件 strChanged 调用 updatestr 方法。 每次调用 updatestr 时都会创建一个线程并开始调用 updatethr。 这里 textBox1.Text 设置为 str (应该是渐进的 "", "0" , "01", "012", "0123", "01234", "012345")并在退出方法之前等待一秒钟. 使用 lock 语句,在 updatestr 中创建的线程应该在修改 textBox1.Text 之前等待前面的线程结束。 运行 这段代码我获得了 textBox1.Text 的值序列,这些值序列与预期序列不匹配,就好像线程没有按照它们在 updatestr 中创建的顺序启动。 为什么会这样?我该如何解决?提前致谢!

编辑:如果想尝试此代码,您可以将 SystemUtilities.SetControlPropertyThreadSafe(textBox1, "Text", (string)str) 替换为 System.Windows.Forms.MessageBox.Show(str)

我相信您正在寻找不同的线程策略。看来您需要一个线程来维持秩序,这与完成操作的窗体主线程不同。通过使用 BlockingCollection,您可以按顺序让不同的线程对字符串进行操作。

我会这样重写代码:

event strHandler strChanged;
delegate void strHandler(string str);

public Form1()
{
    InitializeComponent();

    Thread th = new Thread(new ThreadStart(updatethr));
    th.IsBackground = true;
    th.Start();

    strChanged += new strHandler(updatestr);
}

BlockingCollection<string> bc = new BlockingCollection<string>();

public void updatestr(string str)
{
    bc.Add(str);
}

private void updatethr()
{
    while(true)
    {
        string str = bc.Take();
        SystemUtilities.SetControlPropertyThreadSafe(textBox1, "Text", (string)str);
        // Not sure why you need this here, other than simulating a long operation.
        // Thread.Sleep(1000); 
    }
}

private void button1_Click(object sender, EventArgs e)
{
    this.Text = write();
}

private string write()
{
    string res = "";
    strChanged(res);
    for (int i = 0; i <= 5; i++)
    {
        res += i.ToString();
        strChanged(res);
    }
    return res;
}