如何在C#中向线程传递参数?
考虑以下代码:如何在C#中向线程传递参数?,c#,multithreading,C#,Multithreading,考虑以下代码: namespace MyThreads { public class HisThread { public int Thread2(int start, int end, int[] arr) { int sum = 0; // foreach (int i in arr) for (int i = start; i <= end; i++)
namespace MyThreads
{
public class HisThread
{
public int Thread2(int start, int end, int[] arr)
{
int sum = 0;
// foreach (int i in arr)
for (int i = start; i <= end; i++)
{
sum += arr[i];
}
return sum;
}
}
public class MyThread
{
public void Thread1()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Hello world " + i);
Thread.Sleep(1);
}
}
}
public class Test
{
public static void Main()
{
int[] arr = new int[30];
for (int i = 0; i < 30; i++ )
{
arr[i] = i;
}
Console.WriteLine("Before start thread");
// thread 1 - without params
MyThread thr = new MyThread();
Thread tid1 = new Thread(new ThreadStart(thr.Thread1)); // this one is OK
tid1.Start();
// thread 2 - with params
HisThread thr2 = new HisThread();
Thread tid2 = new Thread(new ParameterizedThreadStart(thr2.Thread2));
}
}
}
知道怎么解决吗
谢谢委托要求方法接受对象的单个参数
类型:
public delegate void ParameterizedThreadStart(object obj)
也就是说,你的方法应该是
public class HisThread
{
public void Thread2(object obj)
{
// ...
}
}
还有一种方法接受参数:
// thread 2 - with params
HisThread thr2 = new HisThread();
Thread tid2 = new Thread(new ParameterizedThreadStart(thr2.Thread2));
tid2.Start(parameter);
如果您使用的是.NET 4.5,则可以改用:
Task.Run(()=>thr2.Thread2(开始、结束、数组))
这可能有助于:
class MyParameter
{
public int Start, End; //Use Properties for these
public int[] Array; //Use Properties for this
}
然后:
该代码的问题在于
ParameterizedThreadStart
是一种委托类型,这意味着它与特定的方法签名相关联——特别是,该签名是无效方法(对象)
。您的方法Thread2
与该签名不匹配,因此出现编译器错误
那么如何解决呢?这要看情况了
ParameterizedThreadStart
具有该特征,因为它是有史以来最通用的方法。其背后的思想是,您可以传递某个自定义类型的对象,该对象包含函数所需的所有状态,如下所示:
class Params
{
public int Start { get; set; }
public int End { get; set; }
public int[] Array { get; set; }
}
var p = new Params { 0, 0, new int[0] };
var t = new Thread(thr2.Thread2);
t.Start(p);
public int Thread2(object param)
{
var p = (Params)param;
// and now get your arguments as p.Start etc.
}
虽然这是可行的,但它非常笨拙,迫使您放弃Thread2
的最自然的签名。但是,通过插入匿名函数来解包参数,您可以做得更好:
int start = 0, end = 0;
var arr = new int[0];
var t = new Thread(() => thr2.Thread2(start, end, arr));
如果您选择这样做,您必须注意这样一个事实:由于编译器用于将参数传递给thread方法的机制,在定义t
之后但在开始之前更改其值将使Thread2
看到更改的值
为什么它不能编译
因为您的代理与所需签名不匹配
知道怎么解决吗
解决方案1:
创建自己的类型并传递数据
public class MyClass
{
public int start {get;set;};
public int end {get;set;};
public int[] arr {get;set;};
}
public void Thread2(object parameter)
{
MyClass obj = (MyClass)parameter;
//Make use of obj
}
HisThread thr2 = new HisThread();
Thread tid2 = new Thread(new ParameterizedThreadStart(thr2.Thread2));
tid2.Start(new MyClass{...});
解决方案2:
就用一个兰姆达
HisThread thr2 = new HisThread();
Thread tid2 = new Thread(() => thr2.Thread2(param1,param2,param3));
tid2.Start();
但是,如果调用此函数后立即调整变量,则可能会产生一些副作用,因为实际上是通过引用传递变量。尝试以下方法:
Thread thread = new Thread(() => new HisThread().Thread2(0, 3, new int[] { 1, 2, 3, 4 }));
如果您在2.0中:
Thread thread = new Thread(delegate() { new HisThread().Thread2(0, 3, new int[] { 1, 2, 3, 4 }); });
最简单的方法是像这样委派
ThreadStart ts = delegate
{
bool moreWork = DoWork("param1", "param2", "param3");
if (moreWork)
{
DoMoreWork("param1", "param2");
}
};
new Thread(ts).Start();
ParameterizedThreadStart仅适用于类型为“object”的参数。您必须将Thread2的方法签名更改为仅使用“object”类型的参数,如果您使用线程搜索传递参数,您将得到太多的答案。这将非常有用:@SriramSakthivel just copy paste问题,已经修复,谢谢,这种情况经常发生:)
Thread thr2 = new Thread(() => thr2.Thread2(0, 1, arr));
Thread thread = new Thread(() => new HisThread().Thread2(0, 3, new int[] { 1, 2, 3, 4 }));
Thread thread = new Thread(delegate() { new HisThread().Thread2(0, 3, new int[] { 1, 2, 3, 4 }); });
ThreadStart ts = delegate
{
bool moreWork = DoWork("param1", "param2", "param3");
if (moreWork)
{
DoMoreWork("param1", "param2");
}
};
new Thread(ts).Start();