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

本文关键字:运行 线程 顺序 随机 | 更新日期: 2023-09-27 18:35:48

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

    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 时,这个。文本将立即设置为write()函数("012345")的结果。返回的字符串是在 write() 中构建的 res,从空字符串开始,并迭代地附加从 0 到 5 的数字。创建字符串并对于添加到 res的每个数字时,将引发事件 strChanged 调用 updatestr 方法。每次调用 updatetr 时,都会创建一个线程并开始调用 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)

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

我相信

您正在寻找不同的线程策略。看来您需要一个线程来维持顺序,这与完成操作的窗体的主线程不同。通过使用 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;
}