侦听事件的线程

本文关键字:线程 事件 | 更新日期: 2023-09-27 18:00:57

我正在编写一个程序,其中有"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。请给我一个解决方案。

侦听事件的线程

这不是

线程的真正工作方式。您需要单步执行代码以查看发生了什么。归根结底,它会做它所做的事情,因为这就是它的工作方式。

基本上,事件在 ui 线程上引发,因此其余的执行发生在该线程上。您需要在要处理它们的线程中引发事件,这意味着将控制权传递给事件处理程序中的其他线程。

但是,如果您确实设法使其工作,那么您将编写魔鬼代码本身。您正在编写的内容可能会产生巨大的副作用,因为您将有多个线程写入 ui 线程在用于 ui 时可能将其视为其状态的内容。

您正在尝试在初学者的 UI 以外的线程上启动 UI。那是诺诺。

您希望使用异步工作线程模式。

http://msdn.microsoft.com/en-us/library/hh191443.aspx

是新学校的做法。

您还应该阅读有关线程和窗口窗体的信息。我不会用 ui 做太多线程,但是当我这样做时,我总是必须返回并检查它是如何工作的。

顺便说一句,如果您正在创建这样的线程,那么您正在做错;)将有一种更好的方法可以做到这一点,它不依赖于您正确获得所有可变区域/锁和信号量。原子性是个婊子,她会让你成为她的。不要创建线程,让 .net 从中抽象出来,并使用更高级别的应用程序,例如异步等待或任务库。甚至使用异步工作线程模式 - 所有更好的方法。

您在所有表单上都收到"不是这个"消息,因为在下面的行中

if (x == Thread.CurrentThread.Name)

Thread.CurrentThread.Namenull.

发生这种情况是因为调用m(textBox1.Text)的线程是主 UI 线程,而不是您在实例化 NewClient1 对象([线程] 被命名(时创建的线程。主 UI 线程没有设置名称,因此为空。

解决方法是,可以在 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 |        |                          |
+-------------------------+        +--------------------------+

您将运行"alpha"的线程命名为"alpha",这不一定(很可能不是(在您检查名称的 NewClient 上拥有/运行处理程序的线程。

如果您需要识别客户端,为什么不给他们一个标识符属性?