在C#开发中,线程是很重要的一个方面。一般在线程中会处理一些常规的周期性的事务,我们会通过Thread.Sleep(int)或者Thread.Join(int)这两种方式来使线程休眠(阻塞)。这两者的区别在于Sleep是线程类的静态方法,当执行Sleep方法时,所有的线程都会被休眠;而Join方法则是实例方法,只针对本线程起作用而已。
不论是Sleep或者是Join方法我们一般都会放在线程初始化中ThreadStart委托所设置的情景中进行。如下例所示:
class ThreadProcess
{
Thread t1;;
public ThreadProcess()
{
t1 = new Thread(new ThreadStart(this.threading));
}
public void start()
{
t1.Start();
}
private void threading()
{
while (true)
{
//do something
t1.Join(20000);
}
}
在这个例子中每隔20秒左右线程就会苏醒一次执行某个动作。而整个线程的启动完全有threading这个方法所决定的。有ThreadStart这个委托的定义我们可以知道这是一个不带参数的委托。如果我们需要在线程的执行过程中如果我们需要有参数传入,则在初始化线程的时候使用new ParameterizedThreadStart这个初始化参数。根据这个参数的形式我们可以知道,在初始化时可以传入一个object类型的参数,而且这个object参数也只能在start的时候起到作用。当指定到线程体时,这个参数依然不能发挥作用,而且参数的类型和个数都受到了极大的限制。那么有没有什么办法能够在while(true)的循环中使得外部参数能够在线程体的执行过程中参与呢?
办法就是使用Observer的观察者模式并且结合.NET特有的委托-事件处理模式进行处理。代码如下所示:
delegate void doThread();
class ThreadProcess
{
WrITeFile wf;
Thread t1;
event doThread dt;
public ThreadProcess()
{
wf = new WriteFile();
t1 = new Thread(new ThreadStart(this.threading));
new ParameterizedThreadStart
dt += wf.WirteLog;
}
public void start()
{
t1.Start();
}
private void threading()
{
while (true)
{
dt();
t1.Join(20000);
}
}
}
class WriteFile
{
StreamWriter sw=null;
int count = 1;
string content;
public WriteFile()
{
DirectoryInfo directory = new DirectoryInfo(@"../../log");
int i = 0;
if (!directory.Exists)
{
directory.Create();
}
FileInfo[] fis = directory.GetFiles(DateTime.Now.ToString( "yyyyMMdd-" ) + "*.log" , SearchOption.TopDirectoryOnly);
foreach (FileInfo fi in fis)
{
if (fi.Length > 1024)
{
i++;
continue ;
}
else
{
sw = fi.AppendText();
break ;
}
}
if (sw == null )
{
sw = File.AppendText(directory.ToString() + @ "/" + DateTime.Now.ToString( "yyyyMMdd-" ) + i.ToString() + @ ".log" );
}
}
public void WirteLog()
{
if (count == 1)
{
count++;
content = DateTime.Now.ToString() + ":第一次启动" ;
}
else
{
content = DateTime.Now.ToString() + ":服务启动" ;
}
sw.WriteLine(content);
sw.Flush();
}
}
在上面的代码中,我们首先声明了一个委托doThread(),然后在类ThreadProcess声明了该委托类型的一个事件dt。同时为该事件绑定了处理事件的委托方法也就是WriteFile类中的WirteLog方法。这样我们就知道当触发了事件dt时,WriteLog方法会被通知到并且开始执行。
接着我们看到了在线程的委托方法中在线程执行中我们触发了dt事件。这就意味着WriteFile类中的WirteLog方法将被召唤执行。由于WriteLog是线程外的方法,所以他使用的参数自然也就是WriteFile自己的参数,这样线程就和处理逻辑脱钩了,而被委托的方法使用的又是外部方法和参数,自然也就达到了我们所谓的外部参数传入线程的目的。
在这个示例中,线程仅仅起到了一个定时的消息触发的角色而已,真正的线程处理国际完全以后事件触发以后绑定的委托来进行操作。这样外部参数自然流入到线程内部去了。
详细出处参考:http://www.itqun.net/content-detail/121019_2.html