我正在编写一个程序,其中我有' n'线程数,每个都命名为' 0',' 1',' 2',' 3',..' n- 1'分别。这些线程中的每一个都在监听主线程上的按钮单击事件。单击该按钮时,每个线程必须将文本框中的文本与其名称进行比较。如果文本相同,则线程必须显示它,否则,它必须显示"不是这个"。
public partial class Form1 : Form
{
public delegate void MyEventHandler(string s);
public event MyEventHandler m;
static int ncarr;
NewClient1[] nc = new NewClient1[5];
string x;
Thread[] th = new Thread[5];
static int tc;
public Form1()
{
InitializeComponent();
ncarr = 0;
tc = 0;
}
public void alpha()
{
Thread.CurrentThread.Name = (tc-1).ToString();
nc[tc - 1] = new NewClient1();
this.m += nc[tc-1].myFunc;
nc[tc-1].Text = Thread.CurrentThread.Name;
nc[tc-1].ShowDialog();
}
private void button1_Click(object sender, EventArgs e)
{
if (m != null)
{
m(textBox1.Text);
}
else
{
label1.Text = "m is null";
}
}
private void button2_Click(object sender, EventArgs e)
{
th[tc] = new Thread(new ThreadStart(alpha));
tc++;
th[tc-1].Start();
}
}
public partial class NewClient1 : Form
{
public delegate void SetPrint (string x);
public NewClient1()
{
//if (this.label1.InvokeRequired)
InitializeComponent();
}
public void myFunc(string x)
{
//int i = Int32.Parse(x);
if (x == Thread.CurrentThread.Name)
{
string y = "this is being printed by " + Thread.CurrentThread.Name;
y += "\n Message received = " + x;
print(y);
}
else
{
string y = "not this";
print(y);
}
}
public void print(string x)
{
if (this.label1.InvokeRequired == true)
{
SetPrint d = new SetPrint(print);
this.Invoke(d, new object[] { x });
}
else
{
label1.Text = x;
}
}
}
但是当我创建多个线程甚至输入' 0'在文本框中,所有线程都显示"而不是"。
当我尝试调试时,在行" if(x == Thread.CurrentThread.Name)"中,所有线程的Thread.CurrentThread.Name的值为NULL。请给我一个解决方案。
答案 0 :(得分:1)
这不是线程的工作原理。 您需要单步执行代码才能看到正在发生的事情。在一天结束时,它会做它所做的事情,因为它是如何工作的。
基本上在ui线程上引发事件,因此执行的其余部分发生在该线程上。您需要在要处理它们的线程中引发事件,这意味着将控制权传递给事件处理程序中的其他线程。
如果你真的想让它工作,那么你就会编写恶魔代码本身。你正在写一些会产生潜在巨大副作用的东西,因为你会有多个线程写入ui线程在被用作ui时可能被视为其状态的东西。
你正试图在ui之外的线程上启动ui。那是一个非诺。
您想使用异步工作模式。
http://msdn.microsoft.com/en-us/library/hh191443.aspx
是新学校的做法。
你还应该阅读有关线程和windows表单的内容。我没有用ui做很多线程,但是当我这样做时,我总是要回去检查它是如何工作的。
顺便说一句,如果你正在创建这样的线程,那么你做错了;)将有一个更好的方法来做到这一点,而不依赖于你获得所有可变区域/锁定和信号量正确。原子性是一个婊子,她会让你成为她的。不要创建线程,让.net摘要,并使用更高级别的appraoches,如async await或任务库。甚至使用异步工作者模式 - 所有更好的方法。
答案 1 :(得分:0)
您命名运行' alpha'的线程,这不一定(很可能不是)在您检查名称的NewClient上拥有/运行处理程序的线程。
如果您需要识别客户,为什么不给他们一个标识符属性?
答案 2 :(得分:0)
您在所有表单上收到“not this”消息,因为在下面一行
if (x == Thread.CurrentThread.Name)
Thread.CurrentThread.Name
是null
。
这种情况正在发生,因为调用m(textBox1.Text)
的线程是主UI线程,而不是在实例化[线程]命名的NewClient1对象时创建的线程。主UI线程没有Name设置,因此它为null。
作为一种变通方法,您可以在NewClient1类中创建一个属性并设置它并对该属性的值执行比较。
public string NewClientName { get; set; }
. . .
if (x == NewClientName)
{
. . .
}
图示,线程调用可以表示如下
+-------------------------+ +--------------------------+
| Main UI Thread | | NewClient thread |
| (Name = null) | | (Name set below) |
+-------------------------+ +--------------------------+
| on Button Click | | |
| > create Thread--------|------> | Create object nc |
| | | > set this thread's name |
| | | |
| on btn2 Click | | |
| >invoke mc(txt.Text) | | |
| > calls nc.myFunc | | |
| | | |
|//so CurrentThread.Name | | |
|//is null in this Thread | | |
+-------------------------+ +--------------------------+