启动线程时如何将参数传递给方法? [复制]

Posted

技术标签:

【中文标题】启动线程时如何将参数传递给方法? [复制]【英文标题】: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 【参考方案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% 正确的。

以上是关于启动线程时如何将参数传递给方法? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法将参数传递给Runnable? [复制]

当我们将对象作为参数传递给方法时,为啥会调用复制构造函数?

如何将传递给我的 bash 脚本的所有参数传递给我的函数? [复制]

如何将多个重复的参数传递给 CUDA 内核

如何将参数传递给 Thread 中的 ThreadStart 方法?

Python:如何将参数传递给线程作业(回调)