.NET异步程序设计——给线程传递数据
0. 前情说明
首先我们都知道,创建一个线程执行一个无参函数,则方式如下:
//期望在线程中执行的函数
static void Do()
{
Console.WriteLine("Create Thread");
}
//创建线程执行函数
static void Main(string[] ars)
{
Thread thread=new Thread(Do);
thread.Start();
Console.ReadKey();
}
1. ParameterizedThreadStart类型的委托
使用以ParameterizedThreadStart
类型的委托为参数的Thread对象构造函数,并使用Thread.Start()来传递参数
这里首先说明一下,上文中示例,创建Thread对象,使用的构造函数的参数是ThreadStart
类型的委托
而Thread()方法在.net中有四个重载,我们可以使用其参数类型为ParameterizedThreadStart
类型的构造函数,实现线程中执行带参数的函数,即往线程中传递数据。
注意:
-
是使用
Thread.Start(object param)
传递参数的 -
ParameterizedThreadStart
类型的委托是:参数类型是object类型,无返回值的 -
因为
ParameterizedThreadStart
类型的委托的参数类型是object类型,所以我们需要修改期望在新线程中行的方法,将其参数改为object类型,在方法中使用时在进行拆箱
示例:
static void Do(object obj)
{
int n = (int)obj;
Console.WriteLine($"方法1:新开线程执行方法,其参数是{n}");
}
static void Main(string[] args)
{
Thread thread = new Thread(Do);//这里的Do函数就是ParameterizedThreadStart类型的委托
int n = 999;
thread.Start(n);//在Start函数中传递参数
}
2. 使用自定义类
2.1 简单示例及说明
将方法封装在类中,则在自定义类实例化的时候,实现传递参数
这里我们依旧是使用Thread对象的参数类型为ThreadStart类型的构造函数,但是我们需要在新线程中执行的有参函数封装在一个类中
在类的实例化时,实现传递参数
【注意】:需要注意的是这个自定义的类的实例化对像 不要
示例:
有一个期望在新线程中执行的有参函数如下
pubic void Do(string param)
{
Console.WriteLine($"新开线程执行方法,其参数是{param}");
}
我们可以这样封装该方法,并在创建线程并执行该方法
public class MyClass
{
public int param { get; set; }
public MyClass(int n)
{
this.param = n;
}
public void Do()
{
Console.WriteLine($"方法2:新开线程执行方法,其参数是{param}");
}
}
static void Main(string[] args)
{
MyClass myClass=new MyClass(999);
Thread thread =new Thread(myClass.Do);
}
2.2 获取返回值
获取新线程执行的函数的返回值,其思路和上面一样,在自定义类中添加一个属性,作为返回值
class TempClass2
{
public int X { get; set; }
public int Y { get; set; }
public int Ret { get; set; }
public void DoWithParam()
{
Ret = X + Y;
}
}
static void Main(string[] args)
{
TempClass2 tempClass2 = new TempClass2() { X = 1, Y = 2 };
Thread thread = new Thread(tempClass2.DoWithParam);
thread.Start();
thread.Join();//注意这里表示tempClass线程执行完成
Console.WriteLine($"实现获取到返回值:{tempClass2.Ret}");
}
3. 使用Lambda表达式(推荐方式)
使用Lambda表达式调用期望在新线程中执行的函数,此时可以指定具体的参数值,即实现往线程中的传递数据
这是目前最方便的往线程中传递数据的方式
使用的Thread构造函数的ParameterizedThreadStart类型的参数,只能往线程中传递一个Object类型的参数,而使用Lambda表达式到参数个数无限制。
所以当我们需要创建一个新线程执行一个多参数的函数的时候,可以使用Lambda表达式,而不是修改待调用函数的参数个数
示例:
//期望在新线程中执行的方法
static void Do(int n, int m)
{
Console.WriteLine(n * m);
}
static void Main(string[] args)
{
Thread thread1 = new Thread(() => Do(2, 3));//定义一个Lambda表达式,调用Do()函数
thread1.Start();
//其实这里我们就是可以将所有的函数逻辑直接写在Lambda表达式中,从而更加方便
Thread thread2 = new Thread(() => { Console.WriteLine(2 * 3); });
thread2.Start();
}