我认为标题不言自明。简单地说,我有一些以随机顺序运行的线程,而不是我计划的顺序。 这是一个示例代码:
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,&#34; Text&#34;,(string)str)是一个将textBox1.Text设置为str的函数(用于避免跨线程异常)。 当你按下button1 this.Text将立即设置为write()函数的结果(&#34; 012345&#34;)。 返回的字符串是从空字符串开始在write()内部构建的res,并且迭代地附加从0到5的数字。 创建字符串并将每个数字添加到res时,将引发事件strChanged,调用updatestr方法。 每次调用updatestr时都会创建一个线程并开始调用updatethr。 这里textBox1.Text设置为str(应该逐步&#34;&#34;,&#34; 0&#34;,&#34; 01&#34;,&#34; 012&#34;,& #34; 0123&#34;,&#34; 01234&#34;,&#34; 012345&#34;)并在退出方法前等待一秒钟。 使用lock语句,updatestr中创建的线程应该在修改textBox1.Text之前等待前一个线程的结束。 运行此代码我获取textBox1.Text的值序列,这些值不匹配预期的序列,就像线程不按照在updatestr中创建的顺序开始一样。 为什么会这样?我该如何解决这个问题?提前谢谢!
编辑:如果想尝试此代码,您可以使用System.Windows.Forms.MessageBox.Show(str)
答案 0 :(得分:1)
我相信您正在寻找不同的线程策略。看来你需要一个单独的线程来维护顺序,这与Form的主线程不同,以完成一个操作。通过使用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;
}