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