C# ThreadStart与参数方法

C# ThreadStart与参数方法,c#,winforms,multithreading,C#,Winforms,Multithreading,我正在尝试在.Net中学习线程 你们中的许多人一定已经看到了这一点: private void button1_Click(object sender, EventArgs e) { Thread t = new Thread(new ThreadStart(loop)); t.Start(); } private void loop() { for (int i = 0; i < 100000; i++) { textBox1.Text

我正在尝试在.Net中学习线程

你们中的许多人一定已经看到了这一点:

private void button1_Click(object sender, EventArgs e)
{
    Thread t = new Thread(new ThreadStart(loop));
    t.Start();
}

private void loop()
{
    for (int i = 0; i < 100000; i++)
    {
        textBox1.Text = i.ToString();
    }
}
private void按钮1\u单击(对象发送者,事件参数e)
{
线程t=新线程(新线程开始(循环));
t、 Start();
}
私有void循环()
{
对于(int i=0;i<100000;i++)
{
textBox1.Text=i.ToString();
}
}
它工作得很好,但是如果我的循环方法中有参数,比如:

private void loop(string str)
{
    for (int i = 0; i < 100000; i++)
    {
        textBox1.Text = i + str;
    }
}
private void循环(string str)
{
对于(int i=0;i<100000;i++)
{
textBox1.Text=i+str;
}
}

那么如何在我的ThreadStart中调用这个方法,因为ThreadStart只接受方法名。那么如何在不同的线程中调用循环方法呢?

您应该改用ParameterizedThreadStart:

threadt=新线程(新的参数化线程启动(循环));
t、 启动(“Foo”);
//请注意,此处使用对象来匹配委托签名
私有void循环(对象状态)
{
var str=状态为字符串;
对于(int i=0;i<100000;i++)
{
//无论如何,这是非法的:
//textBox1.Text=i+str;
//您需要调用回UI线程以访问控件的属性:
textBox1.Invoke(()=>{textBox1.Text=i+str;});
}
}

您应该改用ParameterizedThreadStart:

threadt=新线程(新的参数化线程启动(循环));
t、 启动(“Foo”);
//请注意,此处使用对象来匹配委托签名
私有void循环(对象状态)
{
var str=状态为字符串;
对于(int i=0;i<100000;i++)
{
//无论如何,这是非法的:
//textBox1.Text=i+str;
//您需要调用回UI线程以访问控件的属性:
textBox1.Invoke(()=>{textBox1.Text=i+str;});
}
}

有一个ParameterizedThreadStart类,在实例化线程时,可以将带有单个参数的委托转换为该类:

private void button1_Click(object sender, EventArgs e)
{
    Thread t = new Thread(new ParameterizedThreadStart(loop));
    t.Start(str);
}

private void loop(string str)
{
    for (int i = 0; i < 100000; i++)
    {
        //the code you had is a no-no when you are multithreading;
        //all UI updates must occur on the main thread
        //textBox1.Text = i + str;
        UpdateTextBoxText(textBox1, i+str);
    }
}

private void UpdateTextBoxText(TextBox textBox, string text)
{
   //the method will invoke itself on the main thread if it isn't already running there
   if(InvokeRequired)
   {
      this.Invoke((MethodInvoker)(()=>UpdateTextBoxText(TextBox textBox, string text)));
      return;
   }

   textBox.Text = text;
}
private void按钮1\u单击(对象发送者,事件参数e)
{
线程t=新线程(新的参数化线程启动(循环));
t、 启动(str);
}
私有void循环(字符串str)
{
对于(int i=0;i<100000;i++)
{
//当你使用多线程时,你的代码是一个禁忌;
//所有UI更新必须在主线程上进行
//textBox1.Text=i+str;
UpdateTextBoxText(textBox1,i+str);
}
}
私有void UpdateTextBoxText(文本框,字符串文本)
{
//如果该方法尚未在主线程上运行,它将在主线程上调用自身
如果(需要调用)
{
this.Invoke((MethodInvoker)(()=>UpdateTextBoxText(TextBox TextBox,string text));
返回;
}
Text=Text;
}
如果不需要对线程的启动和停止进行细粒度控制,可以将其留给线程池,并使用Delegate.BeginInvoke:

private void button1_Click(object sender, EventArgs e)
{
    Action<string> method = loop;

    method.BeginInvoke(str, null, null);
}

private void loop(string str)
{
    for (int i = 0; i < 100000; i++)
    {
        //textBox1.Text = i + str;
        UpdateTextBoxText(textBox1, i+str);
    }
}

private void UpdateTextBoxText(TextBox textBox, string text)
{
   //the method will invoke itself on the main thread if it isn't already running there
   if(InvokeRequired)
   {
      this.Invoke((MethodInvoker)(()=>UpdateTextBoxText(textBox, text)));
      return;
   }

   textBox.Text = text;
}
private void按钮1\u单击(对象发送者,事件参数e)
{
动作方法=循环;
方法。BeginInvoke(str,null,null);
}
私有void循环(字符串str)
{
对于(int i=0;i<100000;i++)
{
//textBox1.Text=i+str;
UpdateTextBoxText(textBox1,i+str);
}
}
私有void UpdateTextBoxText(文本框,字符串文本)
{
//如果该方法尚未在主线程上运行,它将在主线程上调用自身
如果(需要调用)
{
this.Invoke((MethodInvoker)(()=>UpdateTextBoxText(textBox,text));
返回;
}
Text=Text;
}

有一个ParameterizedThreadStart类,在实例化线程时,可以将带有单个参数的委托转换为该类:

private void button1_Click(object sender, EventArgs e)
{
    Thread t = new Thread(new ParameterizedThreadStart(loop));
    t.Start(str);
}

private void loop(string str)
{
    for (int i = 0; i < 100000; i++)
    {
        //the code you had is a no-no when you are multithreading;
        //all UI updates must occur on the main thread
        //textBox1.Text = i + str;
        UpdateTextBoxText(textBox1, i+str);
    }
}

private void UpdateTextBoxText(TextBox textBox, string text)
{
   //the method will invoke itself on the main thread if it isn't already running there
   if(InvokeRequired)
   {
      this.Invoke((MethodInvoker)(()=>UpdateTextBoxText(TextBox textBox, string text)));
      return;
   }

   textBox.Text = text;
}
private void按钮1\u单击(对象发送者,事件参数e)
{
线程t=新线程(新的参数化线程启动(循环));
t、 启动(str);
}
私有void循环(字符串str)
{
对于(int i=0;i<100000;i++)
{
//当你使用多线程时,你的代码是一个禁忌;
//所有UI更新必须在主线程上进行
//textBox1.Text=i+str;
UpdateTextBoxText(textBox1,i+str);
}
}
私有void UpdateTextBoxText(文本框,字符串文本)
{
//如果该方法尚未在主线程上运行,它将在主线程上调用自身
如果(需要调用)
{
this.Invoke((MethodInvoker)(()=>UpdateTextBoxText(TextBox TextBox,string text));
返回;
}
Text=Text;
}
如果不需要对线程的启动和停止进行细粒度控制,可以将其留给线程池,并使用Delegate.BeginInvoke:

private void button1_Click(object sender, EventArgs e)
{
    Action<string> method = loop;

    method.BeginInvoke(str, null, null);
}

private void loop(string str)
{
    for (int i = 0; i < 100000; i++)
    {
        //textBox1.Text = i + str;
        UpdateTextBoxText(textBox1, i+str);
    }
}

private void UpdateTextBoxText(TextBox textBox, string text)
{
   //the method will invoke itself on the main thread if it isn't already running there
   if(InvokeRequired)
   {
      this.Invoke((MethodInvoker)(()=>UpdateTextBoxText(textBox, text)));
      return;
   }

   textBox.Text = text;
}
private void按钮1\u单击(对象发送者,事件参数e)
{
动作方法=循环;
方法。BeginInvoke(str,null,null);
}
私有void循环(字符串str)
{
对于(int i=0;i<100000;i++)
{
//textBox1.Text=i+str;
UpdateTextBoxText(textBox1,i+str);
}
}
私有void UpdateTextBoxText(文本框,字符串文本)
{
//如果该方法尚未在主线程上运行,它将在主线程上调用自身
如果(需要调用)
{
this.Invoke((MethodInvoker)(()=>UpdateTextBoxText(textBox,text));
返回;
}
Text=Text;
}
像这样:

new Thread(() => loop("MyString")).Start();
您甚至不必处理ThreadStart/ParameterizedThreadStart。

如下所示:

new Thread(() => loop("MyString")).Start();
Thread t = new Thread(new ParameterizedThreadStart(loop));
t.Start("Hello world");

private void loop(object obj)
{
    string str = (string)obj;

    for (int i = 0; i < 100000; i++)
    {
        // Don't do this: you can't change a control from another thread. Danger Will Robinson!
        textBox1.Text = i + str;
    }
}
您甚至不必处理ThreadStart/ParameterizedThreadStart

Thread t = new Thread(new ParameterizedThreadStart(loop));
t.Start("Hello world");

private void loop(object obj)
{
    string str = (string)obj;

    for (int i = 0; i < 100000; i++)
    {
        // Don't do this: you can't change a control from another thread. Danger Will Robinson!
        textBox1.Text = i + str;
    }
}
通过这种方式,匿名方法将在
str
附近“关闭”,它将类似于您传递了参数。类似,因为关闭变量存在差异/问题。实际上,我会写一些类似的东西:

string str = "Hello world";

{
    string str2 = str;

    Thread t = new Thread(() => {
        for (int i = 0; i < 100000; i++)
        {
            // Don't do this: you can't change a control from another thread. Danger Will Robinson! 
            textBox1.Text = i + str2;
        }
    });

    t.Start();
}
string str=“Hello world”;
{
字符串str2=str;
线程t=新线程(()=>{
对于(int i=0;i<100000;i++)
{
//不要这样做:你不能从另一个线程更改控件。危险将是Robinson!
textBox1.Text=i+str2;
}
});
t、 Start();
}
这样其他人就不能“触摸”str2了

如果您需要,我可以在上面找到一些答案,以便解释这个“问题”