【问题标题】:How can I pass a parameter to a method when I start a thread? [duplicate]启动线程时如何将参数传递给方法? [复制]
【发布时间】:2021-10-18 00:58:01
【问题描述】:

我想在线程中启动方法时将参数传递给方法。

例如,我还想在 k=0 到 k=10 的 for 循环的上下文中执行此操作。

此外,我希望每个线程彼此独立。到目前为止,我有这个:

for (int k = 0; k < 3; k++)
{
new Thread(() => Method2(list[k])).Start();
}

其中Method2应该做一些处理,定义如下(body不重要,它基本上是创建并写入文件):

public static void Method2(string SYM)

不知何故,当我运行代码时,我确实创建了三个线程,但传递给每个线程的参数似乎只是所有三个线程的 list[2] 参数。我希望每个线程分别有 list[0] list[1] list[3] 作为参数。

【问题讨论】:

  • 新线程((obj) => Method2(list[(int)obj)).Start(k);
  • 或者... new Thread((obj) => Method2((string)obj)).Start(list[k]);
  • 我认为问题在于变量 k 是线程之间共享的。试试foreach( int k in Enumerable.Range( 0, 3 ) )
  • 为什么要特别使用线程而不是任务?
  • 您是否有意“设置并忘记”您创建的每个Thread

标签: c# multithreading


【解决方案1】:

我认为解决此问题的更好方法是使用Parallel.ForEach

static void Main( string[ ] _ )
{
    var list = new List<string> { "Value1", "Value2", "Value3" };
    Parallel.ForEach( list, value => Method2( value ) );
}

这是使用Task's(设置和遗忘)的另一种解决方案。

static void Main( string[ ] _ )
{
    var list = new List<string> { "Value1", "Value2", "Value3" };            
    for ( int i = 0; i < list.Count; i++ )
    {
        var index = i;
        // Set and forget.
        Task.Run( ( ) => Method2( list[ index ] ) );                                
    }
}

这是使用Task 的另一种解决方案,但这次你await 为每个Task 完成。

static async Task Main( string[ ] _ )
{
    var list = new List<string> { "Value1", "Value2", "Value3" };
    var tasks = new List<Task>( list.Count );
    for ( int i = 0; i < list.Count; i++ )
    {
        var index = i;
        // Set and forget.
        tasks.Add( Task.Run( ( ) => Method2( list[ index ] ) ) ); 
    }

    await Task.WhenAll( tasks );
}

如果您不喜欢这样并想坚持使用您的解决方案,那么您可以在 for 循环中本地捕获 i 变量。

for ( int i = 0; i < list.Count; i++ )
{
    var index = i;
    new Thread( ( ) => Method2( list[ index ] ) ).Start( );
}

每个Thread 都将拥有自己的index 变量副本,而不是每个Thread 共享对i 变量的引用(这是您当前正在执行的操作)。

您的for 循环在第一个Thread 开始之前完成;因此,当其中一个 Thread 最终启动时,它会看到 i 设置为的最后一个值(在您的情况下为 3)。

如果你不相信我运行下面的代码。

static void Main( string[ ] _ )
{       
    for ( int i = 0; i < 3; i++ )
    {
        new Thread( ( ) => Console.WriteLine( $"{i}" ) ).Start( );
        Thread.Sleep( 1500 );
    }            
    Console.ReadLine( );
 }

应该看到打印到控制台的值,012。 现在,运行这段代码(注意我删除了Thread.Sleep:

static void Main( string[ ] _ )
{       
    for ( int i = 0; i < 3; i++ )
    {
        new Thread( ( ) => Console.WriteLine( $"{i}" ) ).Start( );
    }            
    Console.ReadLine( );
}

应该看到打印到控制台的值,333

【讨论】:

  • Each invocation of Method2 will be done is a separate thread. 不是 100% 正确的。
猜你喜欢
  • 2016-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-02
  • 2020-09-18
  • 1970-01-01
  • 2023-03-12
  • 2010-10-26
相关资源
最近更新 更多