好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

厚积薄发,丰富的公用类库积累,助你高效进行系统开发(11)各种线程相关操作类

厚积薄发,丰富的公用类库积累,助你高效进行系统开发(11)各种线程相关操作类

俗话说,一个好汉十个帮,众人拾柴火焰高等都说明一个道理,有更多的资源,更丰富的积累,都是助你走向成功,走向顶峰的推动力。

本篇的公用类库的介绍主题是程序开发中多线程操作环境中,常用到的线程相关类,本篇随笔介绍包含单件创建辅助类、Timer定时器、委托处理辅助类、队列的线程处理服务辅助类、可以取消执行操作的线程池辅助类、线程池辅助类、线程辅助类等对象,这些辅助类覆盖了多线程开发中绝大多数的应用。良好的封装及操作,给我们提供非常方便、高效的线程操作处理。

本篇继续继续整理优化已有的共用类库,并继续发表随笔介绍公用类库的接口方法以及详细使用操作,力求给自己继续优化,积攒更丰富的公用类库资源,加深了解的同时,也给大家展现公用类库好的方面。

厚积薄发,丰富的公用类库积累,助你高效进行系统开发(10)---各种线程同步的集合类
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(9)----各种常用辅助类
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(8)----非对称加密、BASE64加密、MD5等常用加密处理
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(7)-----声音播放、硬件信息、键盘模拟及钩子、鼠标模拟及钩子等设备相关  
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(6)----全屏截图、图标获取、图片打印、页面预览截屏、图片复杂操作等
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(5)----热键、多线程、窗体动画冻结等窗体操作
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(4)----CSV、Excel、INI文件、独立存储等文件相关
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(3)----数据库相关操作
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(2)----常用操作
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(1)----开篇总结

1、单件操作辅助类 Singleton。   

实现效果

1) 本辅助类主要是用来方便实现类对象的单件实例操作,减少重复写单件实现代码的繁琐,简化类的代码。 

2)创建一个类对象的单件实例,类对象的构造函数不能为Public修饰符的,一般为private。

实现代码

1)辅助类提供的方法源码如下所示: 

 ///   <summary>      
/// 创建一个类对象的单件实例,类对象的构造函数不能为Public修饰符的,一般为private。
/// </summary>
/// <typeparam name="T"> 待创建的对象类 </typeparam>
public static class Singleton<T> where T : class
{
static volatile T _instance;
static object _lock = new object ();

static Singleton()
{
}

/// <summary>
/// 创建/获取一个可以new的类对象的单件实例
/// </summary>
public static T Instance
{
get
{
if (_instance == null )
lock (_lock)
{
if (_instance == null )
{
ConstructorInfo constructor = null ;

try
{
// 构造函数不包含public修饰符的
constructor = typeof (T).GetConstructor(BindingFlags.Instance |
BindingFlags.NonPublic, null , new Type[ 0 ], null );
}
catch (Exception exception)
{
throw new InvalidOperationException(exception.Message, exception);
}

if (constructor == null || constructor.IsAssembly)
{
throw new InvalidOperationException( string .Format( " 在'{0}'里面没有找到private或者protected的构造函数。 " , typeof (T).Name));
}

_instance = (T)constructor.Invoke( null );
}
}

return _instance;
}
}

复制代码

2)辅助类Singleton的使用例子代码如下所示

 ///   <summary>      
/// 单件测试类
/// </summary>
public class TestSingletonClass
{
/// <summary>
/// 私有构造函数
/// </summary>
private TestSingletonClass()
{
}

public void ShowMessage()
{
MessageUtil.ShowTips( " 单件实例测试函数 " );
}
}

private void btnSingleton_Click( object sender, EventArgs e)
{
// 单件辅助类使用代码
Singleton<TestSingletonClass>.Instance.ShowMessage();
}

复制代码

如果没有使用单件辅助类,那么单件的测试类将会需要这样书写,很明显多了很多行代码,如果每个想单件处理的类都要这样写,代码量还是很可观的,而且比较繁琐。

 ///   <summary>      
/// 单件测试类
/// </summary>
public class TestSingletonClass
{
private static TestSingletonClass m_Instance;

/// <summary>
/// 单件实例
/// </summary>
public static TestSingletonClass Instance
{
get
{
if (m_Instance == null )
{
m_Instance = new TestSingletonClass();
}
return m_Instance;
}
}

/// <summary>
/// 私有构造函数
/// </summary>
private TestSingletonClass()
{
}

public void ShowMessage()
{
MessageUtil.ShowTips( " 单件实例测试函数 " );
}
}

复制代码

2、定期执行某些任务的定时器辅助类Timer。   

实现效果

1)  本辅助类主要是用来方便实现定时器辅助类,功能和另外一个定时器辅助类TimerHelper差不多。

2) 定时器操作,都通过对象锁以及在运行处理事件的时候,动态改变间隔事件为无限等待,处理完成后修改为间隔时间的方式,实现对定时器的正常、安全执行,不会发生运行一半又跳到下一个的处理过程中。 

3).NET提供了3种定时器实现,他们的特点如下所示。该Timer辅助类是基于Threading.Timer的定时器实现。

Server Timers System.Timers.Timer 基于服务器的计时器,位于"工具箱"的“组件”选项卡上 Thread Timers System.Threading.Timer 在编程时使用的线程计时器 Windows Timers System.Windows.Forms.Timer 基于 Windows 的标准计时器,"工具箱"的"Windows 窗体"选项卡上;

实现代码

1)辅助类提供的方法接口如下所示: 

 #region  事件或属性    

/// <summary>
/// 按定时器周期定期引发的事件
/// </summary>
public event EventHandler Elapsed;

/// <summary>
/// 定时器任务间隔(毫秒)
/// </summary>
public int Period { get ; set ; }

/// <summary>
/// 指示是否在方法开始的时候,启动定时器Elapsed事件一次。默认为false。
/// </summary>
public bool RunOnStart { get ; set ; }

#endregion

#region 构造函数

/// <summary>
/// 创建一个定时器
/// </summary>
/// <param name="period"> 定时器间隔 (毫秒) </param>
public Timer( int period) : this (period, false )

/// <summary>
/// 创建一个定时器
/// </summary>
/// <param name="period"> 定时器间隔 (毫秒) </param>
/// <param name="runOnStart"> 指示是否在方法开始的时候,启动定时器Elapsed事件一次 </param>
public Timer( int period, bool runOnStart)

#endregion

#region 方法

/// <summary>
/// 启动定时器
/// </summary>
public void Start()

/// <summary>
/// 停止定时器
/// </summary>
public void Stop()

/// <summary>
/// 等待定时器停止
/// </summary>
public void WaitToStop()


#endregion

复制代码

2)辅助类Timer 的使用例子代码如下所示

 private   void  btnTimer_Click( object  sender, EventArgs e)    
{
WHC.OrderWater.Commons.Threading.Timer timer = new WHC.OrderWater.Commons.Threading.Timer( 1000 , true );
timer.Elapsed += new EventHandler(timer_Elapsed);
timer.Start();
}

void timer_Elapsed( object sender, EventArgs e)
{
if (! this .InvokeRequired)
return ;

this .Invoke( new MethodInvoker( delegate ()
{
this .btnTimer.Text = DateTime.Now.ToLongTimeString();
}));
}

复制代码

3、定时器辅助类TimerHelper,可指定运行间隔、延迟启动时间等操作。   

实现效果

1) 本辅助类主要是用来方便实现定时器辅助类,可指定运行间隔、延迟启动时间等操作。功能和另外一个定时器辅助类Timer差不多。 

2)定时器操作,都通过对象锁以及在运行处理事件的时候,动态改变间隔事件为无限等待,处理完成后修改为间隔时间的方式,实现对定时器的正常、安全执行,不会发生运行一半又跳到下一个的处理过程中。 

实现代码

1)辅助类提供的方法接口如下所示: 

 ///   <summary>      
/// 定时器执行操作的函数原型
/// </summary>
public delegate void TimerExecution();

/// <summary>
/// 定时器执行时调用的操作
/// </summary>
public event TimerExecution Execute;

/// <summary>
/// 创建一个指定时间间隔的定时器,并在指定的延迟后开始启动。(默认间隔为100毫秒)
/// </summary>
public TimerHelper()

/// <summary>
/// 创建一个指定时间间隔的定时器,并在指定的延迟后开始启动。
/// </summary>
/// <param name="interval"> 定时器执行操作的间隔时间(毫秒) </param>
/// <param name="startDelay"> 指定的延迟时间(毫秒) </param>
public TimerHelper( long interval, int startDelay)

/// <summary>
/// 创建一个指定时间间隔的定时器
/// </summary>
/// <param name="interval"> 定时器执行操作的间隔时间(毫秒) </param>
/// <param name="start"> 是否启动 </param>
public TimerHelper( long interval, bool start)

/// <summary>
/// 启动定时器并指定延迟时间(毫秒)
/// </summary>
/// <param name="delayBeforeStart"> 指定延迟时间(毫秒) </param>
public void Start( int delayBeforeStart)

/// <summary>
/// 立即启动定时器
/// </summary>
public void Start()

/// <summary>
/// 暂停定时器
/// 注意:运行中的线程不会被停止
/// </summary>
public void Pause()

/// <summary>
/// 停止定时器
/// 注意:运行中的线程不会被停止
/// </summary>
public void Stop()

/// <summary>
/// 定时器的处理时间
/// </summary>
/// <param name="obj"></param>
public void Tick( object obj)

/// <summary>
/// 定时器的状态
/// </summary>
public TimerState State

/// <summary>
/// 获取或设置定时器的运行间隔
/// </summary>
public long Interval

复制代码

2)辅助类 TimerHelper 的使用例子代码如下所示

 public  FrmNewHouse()    
{
InitializeComponent();

if (! this .DesignMode)
{
this .winGridViewPager1.OnPageChanged += new EventHandler(winGridViewPager1_OnPageChanged);
this .winGridViewPager1.OnStartExport += new EventHandler(winGridViewPager1_OnStartExport);
this .winGridViewPager1.OnRefresh += new EventHandler(winGridViewPager1_OnRefresh);
this .winGridViewPager1.OnGridViewMouseDoubleClick += new EventHandler(winGridViewPager1_OnGridViewMouseDoubleClick);
this .winGridViewPager1.ShowLineNumber = true ;
this .winGridViewPager1.PagerInfo.PageSize = 20 ;
this .winGridViewPager1.BestFitColumnWith = true ;
this .winGridViewPager1.AppendedMenu = this .contextMenuStrip1;
this .winGridViewPager1.gridView1.RowCellStyle += new DevExpress.XtraGrid.Views.Grid.RowCellStyleEventHandler(gridView1_RowCellStyle);

// 使用定时器,定时刷新窗体的数据,并提示客户更新情况
int interval = Portal.gc.GetRefreshSecond(); // 获取定时间隔时间
TimerHelper timer = new TimerHelper(interval, true );
timer.Execute += new TimerHelper.TimerExecution(timer_Execute);
}
}

// 通过Invoke来实现跨线程间的调用
void timer_Execute()
{
if (! this .InvokeRequired)
return ;

this .Invoke( new MethodInvoker( delegate ()
{
NotifyNewHouse();
}));
}

复制代码

4、提供一个队列的线程处理服务辅助类 QueueServer。    

实现效果

1)  本辅助类主要是用来方便实现提供一个队列的线程处理服务操作。QueueServer是一个先入先出(FIFO)的队列处理服务。

实现代码

1)辅助类提供的方法接口如下所示: 

 #region   属性方法    

/// <summary>
/// 是否是背景线程
/// </summary>
public bool IsBackground

/// <summary>
/// 执行队列
/// </summary>
public T[] Items

/// <summary>
/// 队列数量
/// </summary>
public int QueueCount

/// <summary>
/// 将对象加到队列结尾
/// </summary>
/// <param name="item"></param>
public void EnqueueItem(T item)

/// <summary>
/// 清除队列
/// </summary>
public void ClearItems()

#endregion

#region 线程处理

/// <summary>
/// 处理单个元素
/// </summary>
/// <param name="item"> 元素项目 </param>
protected virtual void OnProcessItem(T item)

/// <summary>
/// 处理函数
/// </summary>
public event Action<T> ProcessItem;

#endregion

复制代码

2)辅助类QueueServer的使用例子代码如下所示

  private   void  btnQueneServer_Click( object  sender, EventArgs e)    
{
QueueServer<PreDataInfo> queueServer = new QueueServer<PreDataInfo>();
queueServer.IsBackground = true ;
queueServer.ProcessItem += new Action<PreDataInfo>(queueServer_ProcessItem);

// 循环入队
for ( int i = 0 ; i < 100 ; i++)
{
queueServer.EnqueueItem( new PreDataInfo(i.ToString(), DateTime.Now.ToString()));
Thread.Sleep( 10 );
}
}

/// <summary>
/// 处理每个出队的操作
/// </summary>
void queueServer_ProcessItem(PreDataInfo obj)
{
Console.WriteLine( " {0} : {1} " , obj.Key, obj.Data);
}
}

public class PreDataInfo
{
public string Key;
public string Data;

public PreDataInfo()
{
}

public PreDataInfo( string key, string data)
{
this .Key = key;
this .Data = data;
}
}

复制代码

5、可以取消执行操作的线程池辅助类 AbortableThreadPool。   

实现效果

1) 本辅助类主要是用来方便实现可以取消执行操作的线程池操作。 

2)AbortableThreadPool线程辅助类可以使用常用的多线程处理环境中,也可以使用在有些在运行过程中可能需要取消的线程处理环境中。

实现代码

1)辅助类提供的方法接口如下所示: 

 ///   <summary>          
/// 把执行操作放到队列中。当线程池的线程可用的时候,方法执行。
/// </summary>
/// <param name="callback"> 一个代表将要执行方法的WaitCallback对象 </param>
public static WorkItem QueueUserWorkItem(WaitCallback callback)

/// <summary>
/// 把执行操作放到队列中,并指定了一个对象,它包含将要执行方法的数据。
/// 当线程池的线程可用的时候,方法执行。
/// </summary>
/// <param name="callback"> 一个代表将要执行方法的WaitCallback对象 </param>
/// <param name="state"> 一个对象,它包含将要执行方法的数据 </param>
public static WorkItem QueueUserWorkItem(WaitCallback callback, object state)

/// <summary>
/// 取消指定的队列中的工作项。
/// </summary>
/// <param name="item"> 线程池中取消的项目 </param>
/// <param name="allowAbort"> 如果设置为 <see langword="true"/> 则允许终止线程 </param>
/// <returns> 项目队列的状态 </returns>
public static WorkItemStatus Cancel(WorkItem item, bool allowAbort)

/// <summary>
/// 获取指定队列中工作项的状态
/// </summary>
/// <param name="item"> 线程池中工作项 </param>
/// <returns> 工作项的状态 </returns>
public static WorkItemStatus GetStatus(WorkItem item)

/// <summary>
/// 取消所有任务
/// </summary>
/// <param name="allowAbort"> 线程是否终止 </param>
public static void CancelAll( bool allowAbort)

/// <summary>
/// 类似Thread.Join,等待AbortableThreadPool执行完成
/// </summary>
public static void Join()

/// <summary>
/// 类似Thread.Join,等待AbortableThreadPool执行完成
/// </summary>
/// <param name="millisecondsTimeout"> 等待的毫秒数 </param>
/// <returns></returns>
public static bool Join( int millisecondsTimeout)

/// <summary>
/// 类似Thread.Join,等待AbortableThreadPool执行完成
/// </summary>
/// <param name="timeout"> 等待的时间范围 </param>
/// <returns></returns>
public static bool Join(TimeSpan timeout)

/// <summary>
/// 在队列中,还未执行处理的数量
/// </summary>
public static int QueueCount

/// <summary>
/// 在执行中的线程数量
/// </summary>
public static int WorkingCount

复制代码

2)辅助类AbortableThreadPool的使用例子代码如下所示

 private   void  btnAbortableThreadPool_Click( object  sender, EventArgs e)    
{
Console.WriteLine( string .Format( " QueueCount:{0},WorkingCount:{1} " , AbortableThreadPool.QueueCount, AbortableThreadPool.WorkingCount));

WorkItem workItem1 = AbortableThreadPool.QueueUserWorkItem( new WaitCallback(Test));
Console.WriteLine( string .Format( " QueueCount:{0},WorkingCount:{1} " , AbortableThreadPool.QueueCount, AbortableThreadPool.WorkingCount));

WorkItem workItem2 = AbortableThreadPool.QueueUserWorkItem( new WaitCallback(Test));
WorkItem workItem3 = AbortableThreadPool.QueueUserWorkItem( new WaitCallback(Test));
WorkItem workItem4 = AbortableThreadPool.QueueUserWorkItem( new WaitCallback(Test));
WorkItem workItem5 = AbortableThreadPool.QueueUserWorkItem( new WaitCallback(Test));
Console.WriteLine( string .Format( " QueueCount:{0},WorkingCount:{1} " , AbortableThreadPool.QueueCount, AbortableThreadPool.WorkingCount));
Thread.Sleep( 1000 );

Console.WriteLine(AbortableThreadPool.Cancel(workItem1, false ));
Console.WriteLine( string .Format( " QueueCount:{0},WorkingCount:{1} " , AbortableThreadPool.QueueCount, AbortableThreadPool.WorkingCount));
Thread.Sleep( 1000 );

Console.WriteLine(AbortableThreadPool.Cancel(workItem1, true ));
Console.WriteLine( string .Format( " QueueCount:{0},WorkingCount:{1} " , AbortableThreadPool.QueueCount, AbortableThreadPool.WorkingCount));
Thread.Sleep( 1000 );

// AbortableThreadPool.CancelAll(true); // 可取消所有任务
AbortableThreadPool.Join(); // 等待所有任务退出
Console.WriteLine( string .Format( " QueueCount:{0},WorkingCount:{1} " , AbortableThreadPool.QueueCount, AbortableThreadPool.WorkingCount));
}

static void Test( object state)
{
int i = 100 ;
while (i-- > 0 )
{
Console.WriteLine(i);
Thread.Sleep( new Random(( int )DateTime.Now.Ticks).Next( 100 ));
}
}

复制代码



6、委托处理辅助类DelegateHelper。   

实现效果

1) 本辅助类主要是用来方便实现委托的处理。 

2)使用委托处理辅助类DelegateHelper,可以快速执行或者取消一些委托方法的执行。

实现代码

1)辅助类提供的方法接口如下所示: 

 ///   <summary>      
/// 执行委托操作
/// </summary>
/// <param name="target"> 目标委托对象 </param>
/// <param name="args"> 参数 </param>
public static WorkItem InvokeDelegate(Delegate target, params object [] args)

/// <summary>
/// 执行委托操作
/// </summary>
/// <param name="target"> 目标委托对象 </param>
public static WorkItem InvokeDelegate(Delegate target)

/// <summary>
/// 中止指定的队列中委托
/// </summary>
/// <param name="target"> 目标委托对象 </param>
/// <returns> 项目队列中止操作的状态 </returns>
public static WorkItemStatus AbortDelegate(WorkItem target)

复制代码

2)辅助类DelegateHelper的使用例子代码如下所示

 private   void  btnDelegeteHelper_Click( object  sender, EventArgs e)    
{
// 无参数的委托
DelegateHelper.InvokeDelegate( new UpdateTextDelegate( this .UpdateText));

// 有参数的委托
DelegateHelper.InvokeDelegate( new UpdateTextDelegate2( this .UpdateText), 100 );

}
private delegate void UpdateTextDelegate();
private delegate void UpdateTextDelegate2( int count);
private void UpdateText()
{
for ( int i = 0 ; i < 1000 ; i++)
{
Thread.Sleep( 100 );
}
}
private void UpdateText( int count)
{
for ( int i = 0 ; i < count; i++)
{
Thread.Sleep( 100 );
}
}

复制代码

7、线程池辅助操作类 ThreadPoolHelper。   

实现效果

1) 本辅助类主要是用来方便实现线程池辅助操作。。 

实现代码

1)辅助类提供的方法接口如下所示:

 ///   <summary>      
/// 方法委托
/// </summary>
public delegate void WaitCallbackNew();

/// <summary>
/// 把执行方法放到队列中。
/// 当线程池线程变为可用的时候,方法执行。
/// </summary>
/// <param name="callback"> 委托对象 </param>
public static bool QueueUserWorkItem(WaitCallbackNew callback)

/// <summary>
/// 把执行方法放到队列中。
/// 当线程池线程变为可用的时候,方法执行。
/// </summary>
/// <param name="proc"> 委托对象数组 </param>
/// <returns></returns>
public static bool QueueUserWorkItems( params WaitCallbackNew[] proc)

/// <summary>
/// 等待指定数组中所有元素收到信号
/// </summary>
public static bool WaitAll()

/// <summary>
/// 等待指定数组中任何一个元素收到信号
/// </summary>
/// <returns> 满足等待的对象数组索引 </returns>
public static int WaitAny()

复制代码

2)辅助类ThreadPoolHelper的使用例子代码如下所示

 private   void  UpdateText()    
{
for ( int i = 0 ; i < 50 ; i++)
{
Thread.Sleep( 100 );
}
}

private void btnThreadPool_Click( object sender, EventArgs e)
{
ThreadPoolHelper.QueueUserWorkItem( new ThreadPoolHelper.WaitCallbackNew(UpdateText));
ThreadPoolHelper.WaitAny(); // 阻塞主界面线程,到5秒循环结束后,主界面可以操作
}

复制代码

8、线程操作辅助类ThreadHelper。  

实现效果

1) 本辅助类主要是用来方便实现线程的各种操作,包括设置线程名称、优先级等及把执行方法放到队列中执行等基础性的线程操作。

实现代码

1)辅助类提供的方法接口如下所示:

 ///   <summary>      
/// 线程名称,最长不超过10个字符!
/// </summary>
/// <param name="name"> 线程名称 </param>
public static void SetThreadName( string name)

/// <summary>
/// 设置线程优先级
/// </summary>
/// <param name="priority"> 线程优先级 </param>
public static void SetThreadPriority(ThreadPriority priority)

/// <summary>
/// 设置主线程的UI Culture
/// </summary>
/// <param name="cultureName"></param>
public static void SetMainThreadUICulture( string cultureName)

/// <summary>
/// 把执行方法放到队列中,并指定了一个对象,它包含使用该方法的数据。
/// 当线程池线程变为可用的时候,方法执行。
/// </summary>
/// <param name="callBack"> 工作项(WaitCallback)对象 </param>
/// <param name="threadName"> 线程名称,最长不超过10个字符! </param>
/// <param name="priority"> 线程优先级 </param>
public static bool Queue(WaitCallback callBack, string threadName, ThreadPriority priority)

/// <summary>
/// 把执行方法放到队列中,并指定了一个对象,它包含使用该方法的数据。
/// 当线程池线程变为可用的时候,方法执行。
/// </summary>
/// <param name="callBack"> 工作项(WaitCallback)对象 </param>
/// <param name="threadName"> 线程名称,最长不超过10个字符! </param>
/// <param name="state"> 执行方法的数据 </param>
/// <param name="priority"> 线程优先级 </param>
public static bool Queue(WaitCallback callBack, string threadName, object state, ThreadPriority priority)

/// <summary>
/// 线程休眠一段毫秒时间
/// </summary>
/// <param name="millisecondsTimeout"> 一段毫秒时间 </param>
public static void Sleep( int millisecondsTimeout)

/// <summary>
/// 线程休眠一段时间
/// </summary>
/// <param name="timeOut"></param>
public static void Sleep(TimeSpan timeOut)

复制代码

2)辅助类ThreadHelper的使用例子代码如下所示

CHM帮助文档持续更新中,统一下载地址是:  http://www.iqidi.com/download/commonshelp.rar 

最新公用类库DLL+XML注释文件下载地址是: https://files.cnblogs.com/wuhuacong/WHC.OrderWater.Commons.rar  

主要研究技术:代码生成工具、Visio二次开发、送水管理软件等共享软件开发
专注于 Winform开发框架 、WCF开发框架的研究及应用。
  转载请注明出处:
撰写人:伍华聪   http: // www.iqidi.com  
    

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于厚积薄发,丰富的公用类库积累,助你高效进行系统开发(11)各种线程相关操作类的详细内容...

  阅读:41次