【问题标题】:How to create a thread?如何创建线程?
【发布时间】:2009-05-01 12:52:42
【问题描述】:

下面的方法是我想在那个线程中完成的:

public void Startup(int port,string path)
{
    Run(path);
    CRCCheck2();
    CRCCheck1();
    InitializeCodeCave((ushort)port);
}

我尝试了谷歌搜索,但没有任何效果

public void Test(int port,string path)
{
    Thread t = new Thread(Startup(port,path));
}

public void TestA(int port,string path)
{
    Thread t = new Thread(Startup);
    t.Start (port,path);
}

两个都不编译,怎么办?

【问题讨论】:

  • 不起作用,还是无法编译?
  • 您应该指定使用的语言,这样我(我们)就不必猜测了。还说,行不通的就很好。
  • 检查问题标签 - C# 无法编译。
  • 标签中指定了语言。 :)

标签: c# multithreading


【解决方案1】:

以下方式起作用。

// The old way of using ParameterizedThreadStart. This requires a
// method which takes ONE object as the parameter so you need to
// encapsulate the parameters inside one object.
Thread t = new Thread(new ParameterizedThreadStart(StartupA));
t.Start(new MyThreadParams(path, port));

// You can also use an anonymous delegate to do this.
Thread t2 = new Thread(delegate()
{
    StartupB(port, path);
});
t2.Start();

// Or lambda expressions if you are using C# 3.0
Thread t3 = new Thread(() => StartupB(port, path));
t3.Start();

这些示例的启动方法具有以下签名。

public void StartupA(object parameters);

public void StartupB(int port, string path);

【讨论】:

  • 我在使用“旧方式”时遇到错误,但兰巴表达式完美无缺。 :)
  • 阐明了所需的启动方法签名。
  • 很好 - 我刚刚使用“旧”方式在下面发布了一个答案,但没有意识到您可以使用 lambda 表达式来创建更清晰的线程入口点。
  • @John:我强烈鼓励您了解为什么事情有效和无效。我觉得你在这里复制/粘贴,这对你自己和你的客户造成了极大的伤害。
  • @Mikko:甚至你的“旧方式”也在使用 C# 3.0 初始化 ThreadParams 属性的特性:-)。
【解决方案2】:

更新 当前建议的启动任务的方法是简单地使用 Task.Run()

Task.Run(() => foo());

请注意,此方法被描述为启动任务的最佳方式see here

上一个答案

我喜欢 System.Threading.Tasks 中的任务工厂。你可以这样做:

Task.Factory.StartNew(() => 
{
    // Whatever code you want in your thread
});

请注意,任务工厂为您提供了额外的便利选项,例如 ContinueWith

Task.Factory.StartNew(() => {}).ContinueWith((result) => 
{
    // Whatever code should be executed after the newly started thread.
});

还要注意,任务与线程的概念略有不同。它们非常适合 async/await 关键字,请参阅 here

【讨论】:

    【解决方案3】:

    您要运行的方法必须是ThreadStart Delegate。请咨询 MSDN 上的Thread documentation。请注意,您可以从一个闭包开始创建您的两个参数。比如:

    var t = new Thread(() => Startup(port, path));
    

    请注意,您可能需要重新访问您的方法可访问性。如果我看到一个类以这种方式在它自己的公共方法上启动一个线程,我会有点惊讶。

    【讨论】:

    • 我试过了,还是不行。 ThreadStart t = new ThreadStart(Startup);
    • 启动需要两个参数。如果您查看我链接的文档,ThreadStart 不带任何参数。我们可以用闭包作弊,让它看起来像两个(在 3.5 中),或者我们可以使用 ParameterizedThreadStart 并将两个参数捆绑到一个对象中(3.5 之前)。
    【解决方案4】:

    您的示例失败,因为 Thread 方法采用一个或零个参数。要在不传递参数的情况下创建线程,您的代码如下所示:

    void Start()
    {
        // do stuff
    }
    
    void Test()
    {
        new Thread(new ThreadStart(Start)).Start();
    }
    

    如果要将数据传递给线程,则需要将数据封装到单个对象中,无论是您自己设计的自定义类,还是字典对象或其他对象。然后您需要使用 ParameterizedThreadStart 委托,如下所示:

    void Start(object data)
    {
        MyClass myData = (MyClass)myData;
        // do stuff
    }
    
    void Test(MyClass data)
    {
        new Thread(new ParameterizedThreadStart(Start)).Start(data);
    }
    

    【讨论】:

      【解决方案5】:
      public class ThreadParameter
              {
                  public int Port { get; set; }
                  public string Path { get; set; }
              }
      
      
      Thread t = new Thread(new ParameterizedThreadStart(Startup));
      t.Start(new ThreadParameter() { Port = port, Path = path});
      

      使用端口和路径对象创建一个对象并将其传递给 Startup 方法。

      【讨论】:

      • 就在我写你的第一行时,我得到“'Startup' 没有重载匹配委托'System.Threading.ParameterizedThreadStart”
      • 启动需要是“void Startup(object parameters)”。您不能使用“void Startup(ThreadParameter parameters)”,因为您不能将对象传递给该对象。您可以将对象参数转换为 Startup 内的 ThreadParameter。
      • 您必须更改 Startup 方法的签名以接受 ThreadParameter 类.....(您使用 2 个参数创建的类)。
      • 您实际上必须对 Startup 进行签名才能接收一个对象,并在您进入该方法时将其转换为 ThreadParameter 对象。
      猜你喜欢
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      • 2013-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多