a) 使用InterLocked类
InterLocked使用于递增、递减以及更改变量值这类较为简单的操作。如果所有的任务都是在同步上下文中的一些简单操作,那么InterLocked类作为一个非常便捷的方法,可以大大减少需要编写的代码量。笔者没有在如下的试例程序中没有感觉到它的功用,当然 也不排除笔者技术有限未能理解到设计者的心思。
例子8:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
public class InterLocked8
{
public static int i =0;
public void Method1()
{
if (i < 20)
{
Interlocked.Increment(ref i);
}
else
{
Interlocked.Decrement(ref i);
}
Thread.Sleep(500);
Console.WriteLine("Current thread is {0},the value of i is {1}", Thread.CurrentThread.Name, i);
}
}
class MainEntryPoint1
{
public static void Main ()
{
Thread myThread;
InterLocked8 il8 = new InterLocked8();
for (int n = 0; n < 20; n++)
{
myThread = new Thread(new ThreadStart(il8.Method1));
myThread.Name = String.Format("Thread{0}", n);
myThread.Start();
}
Console.ReadLine();
}
}
}
b) 无等待读取
当一个线程处在更改变量值的过程中,另一个线程也要更改该变量的值或需要读取变量值,就会出现同步的问题,前文中已介绍了这些同步技术都用当一个线程执行受保护的代码部分时,就会阻塞其它线程对这部分的操作。但如果所有的线程都只读取这个资源,而不改变它的时候,这样做其实是没有必要与浪费时间的。在。NET中用无等待读取来提供这方面的功能。
例子9:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
public class ReaderWriterClass
{
protected ReaderWriterLock m_readerLock = new ReaderWriterLock();
protected int m_counter = 0;
protected int m_readerBlocks = 0;
protected int m_writerBlocks = 0;
protected void ThreadOneMethod()
{
for (int i = 0; i < 200; i++)
{
try
{
m_readerLock.AcquireReaderLock(0);
try
{
System.Console.WriteLine(m_counter);
}
finally
{
m_readerLock.ReleaseReaderLock();
}
}
catch (Exception )
{
Interlocked.Increment(ref m_readerBlocks);
}
}
}
protected void ThreadTwoMethod()
{
for (int i = 0; i < 100; i++)
{
try
{
m_readerLock.AcquireWriterLock(0);
try
{
Interlocked.Increment(ref m_counter);
}
finally
{
m_readerLock.ReleaseWriterLock();
}
}
catch (Exception)
{
Interlocked.Increment(ref m_writerBlocks);
}
Thread.Sleep(1);
}
}
public int ReaderBlocks
{
get
{
return m_readerBlocks;
}
}
public int WriteerBlocks
{
get
{
return m_writerBlocks;
}
}
static void Main ()
{
ReaderWriterClass exampleClass = new ReaderWriterClass();
Thread threadOne = new Thread(new ThreadStart(exampleClass.ThreadOneMethod));
Thread threadTwo=new Thread(new ThreadStart(exampleClass.ThreadTwoMethod));
threadOne.Start();
threadTwo.Start();
threadOne.Join();
threadTwo.Join();
System.Console.WriteLine("Reader Blocks {0},writer blocks {1}",exampleClass.ReaderBlocks,exampleClass.WriteerBlocks);
System.Console.Read();
}
}
}
第四部分 对非同步线程使用线程池
线程池是可以用来在后台执行多个任务的线程集合。它的提出主要是因为有很多线程是在某一事件被触发之后才发生的,在这一事件发生之前这是处于休眠或者是等待状态,而在它的触发事件之后,它可以得到执行,执行完成以后,又进入休眠状态。
a) WaitCallBack
WaitCallBack表示线程池要执行的回调方法。语法如下:
WaitCallBack [MyCallBack]=new WaitCallBack([ThreadPoolWorkerThreadMethod]);
它的语法与ThreadStart差不多,但它委托的事件有一参数,它委托的事件的申明如下:
例子10:
Static void ThreadPoolWorkerThreadMethod(Object[stateObject])
{
….
}
[stateObject]是一个状态对象,能够将信息传递给辅助线程。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Class1
{
public static void Main ()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
Console.WriteLine("Main thread does some work,then sleeps.");
Thread.Sleep(1000);
Console.WriteLine("Main Thread Exit.");
Console.Read();
}
public static void ThreadProc(object stateInfo)
{
Console.WriteLine("Hello from the thread pool!");
}
}
}
b) 将工作项排入队列
要使用线程池,就要先要调用ThreadPool.QueueUserWorkItem方法将工作项加入队列。语法:
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolThreadMethod));
例程11:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class QueueUserWorkerItem1
{
static void Main ()
{
Console.WriteLine("{Main Thread} Queing the work item.");
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolThreadMethod));
Console.WriteLine("{Main Thread} Press the 'Enter' key t exit the process.");
Console.ReadLine();
Console.WriteLine("{Main Thread} Exiting the process.");
}
static void ThreadPoolThreadMethod(Object stateObject)
{
Console.WriteLine("{Thread Pool} Hello Thread Pool.");
Console.ReadLine();
}
}
}
c) 向线程传递数据
ThreadPool构造函数使用一个WaitCallback委托作为参数,利用这个参数可以向ThreadPool传递任意状态或信息,从而传递给线程方法。
例程12:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class PassAWord10
{
static void Main ()
{
Console.WriteLine("{Main Thread} Queuing the work item.");
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolThreadMethod),"This is a state message");
Console.WriteLine("{Main Thread} Press the 'Enter' Key to exit the process.");
Console.Read();
}
static void ThreadPoolThreadMethod(Object stateObject)
{
Console.WriteLine("{Thread Pool} The data passed in is '"+stateObject.ToString()+"'");
}
}
}