1. 委托的异步性:
2. 异步调用方法:
(1)AsyncCallback委托:
AsyncCallback委托仅仅能够调用那些符合特定模式的方法,这些方法只有一个参数IAsyncResult,而且没有返回值:
public delegate int BinaryOp(int x, int y);
static void Main(string[] args)
{
Console.WriteLine("*****AsyncCallback Delegate Example*****");
Console.WriteLine("Main() invoked on thread {0}", Thread.CurrentThread.ManagedThreadId);
BinaryOp b = new BinaryOp(Add);
IAsyncResult iftAR = b.BeginInvoke(10, 10, new AsyncCallback(AddComplete),null);
Console.ReadLine();
}
static void AddComplete(IAsyncResult itfAr)
{
Console.WriteLine("AddComplete() invoked on thread {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Your addition is complete");
}
static int Add(int x, int y)
{
Console.WriteLine("Add() invoked on thread {0}", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(5000);
return x + y;
}
(2)AsyncResult类的作用:
3.System.Threading命名空间:
System.Tgreading命名空间提供了许多类型用来构建多线程应用程序(具体见MSDN);
4.以编程方式创建次线程:
(1) 创建一个方法作为新线程的入口点;
(2) 创建一个ParameterizedThreadStart(或者ThreadStart)委托,并把在上一步所定义方法的地址传给委托的构造函数;
(3) 创建一个Thread对象,并把ParameterizedThreadStart或ThreadStart委托作为构造函数的参数;
(4) 建立任意初始化线程的特性(名称、优先级等);
(5) 调用Thread.Start()方法。
使用ThreadStart委托:
Thread backgroundThread=new Thread(new ThreadStart(p.PrintNumber));
backgroundThread.Name="Secondary";
backgroundThread.Start();
使用ParameterizedThreadStart委托:
AddParams ap = new AddParams(10, 10);
Thread t = new Thread(new ParameterizedThreadStart(Add));
t.Start(ap)
前台线程和后台线程:
前台线程:能阻止应用程序的终结,一直到所有的前台线程终止后,CLR才能关闭应用程序;
后台线程;在任何时候都可能被忽略。当所有前台线程终止时,应用程序域卸载时,所有的后台线程也会被自动终止。
5.并发问题:
(1)同步访问共享资源的首选技术是C#的lock关键字,这个关键字允许定义一段线程同步的代码语句,采用这项技术,后进入的线程不会中断当前线程,而是停止自身的下一步的执行。Lock关键字需要定义一个标记(即一个对象引用),线程在进入锁定范围的时候必须获得这个标记。比较安全和推荐的方式是声明私有的object成员来作为锁标识。
例:
private object threadLock = new object();
public void PrintNumbers()
{
lock (threadLock)
{
Console.WriteLine("->{0} is executing PrintNumbers()", Thread.CurrentThread.Name);
Console.Write("Your numbers:");
for (int i = 0; i < 10; i++)
{
Random r = new Random();
Thread.Sleep(1000 * r.Next(5));
Console.Write("{0}, ", i);
}
Console.WriteLine();
}
}
}
(2)使用System.Threading.Monitor类型进行同步,System.Threading.Monitor跟lock用法差不多,但是它的控制能力更好,可以只是活动的线程等待一段时间,在当前线程完成操作时,通知等待中的线程,等。
6.CLR线程池:
(1)线程池减少了线程创建、开始和停止的次数,而这提高了效率;
(2)使用线程池,能够使我们将注意力放到业务逻辑上而不是多线程架构师上;
(3)如果需要前台线程或设置优先级别,或者线程池中的线程总是后台线程,且它的优先级是默认的;
(4)如果需要有一个带有固定标识的线程便于退出、挂起或者通过名字发现它。