利用多线程解决多处理器充分利用的问题

在B/S架构的应用中经常会遇到某个过程由于业务逻辑复杂而导致执行时间超长而达不到用户要求的情况。虽然说在IIS中会为每个用户建立一个单独的线程去处理,但是对于单个的用户来说仍然是只有一个线程,而且通常情况下开发的程序都是在主线程中运行。即使服务器有多个处理器,而实际上能够利用的大部分情况只有一个处理器。前一段时间我们公司的产品在为一个客户实施的时候就遇到了这样的问题,客户的服务器上面有4个CPU,而实际上真正在使用的只有一个,因为实际并发的用户基本上是一个,但有一些操作仍然要在一分钟以上。
为了解决这个问题,需要在程序运行的过程中建立新的线程,交给操作系统出分配给空闲的处理器(在单线程的情况下操作系统是不能这么做的)。对于大型项目开发来说就需要一个方便使用的线程处理的Class,经过尝试完成了下面的这个线程处理类。
    /// <summary>
    
/// 无返回值的函数托管
    
/// </summary>

    public delegate void MultiWaitCallback(params object[] Params);
    
/// <summary>
    
/// 有返回值的函数托管
    
/// </summary>

    public delegate object WithReturnMultiWaitCallback(params object[] Params);

    
/// <summary>
    
/// 系统线程管理器
    
/// </summary>

    public class ThreadManager
    
{
        
private static object Invoke(object callback,bool waitFinish,params object[] Params)
        
{
            ThreadState threadState
=new ThreadState(Guid.NewGuid() .ToString() ) ;
            threadState.Parameter 
=Params;
            threadState.Callback
=callback;
            
if(ServerVeriable.CpuNumber>1)
            
{
                ThreadPool.QueueUserWorkItem(
new WaitCallback(ProcThread)  ,threadState);
                
if(waitFinish)
                
{
                    
lock(threadState.SynRoot)
                    
{
                        Monitor.Wait(threadState.SynRoot);
                    }

                }

            }

            
else
            
{
                ProcThread(threadState);
            }

            
return threadState.ReturnValue ;
        }


        
/// <summary>
        
/// 根据服务器的处理器数选择使用线程模式执行托管方法
        
/// </summary>
        
/// <param name="callback">待执行的托管方法</param>
        
/// <param name="waitFinish">是否等待函数完成</param>
        
/// <param name="Params">函数参数</param>

        public static void Invoke(MultiWaitCallback callback,bool waitFinish,params object[] Params)
        
{
            Invoke((
object)callback,waitFinish,Params);
        }


        
/// <summary>
        
/// 根据服务器的处理器数选择使用线程模式执行托管方法。适用于托管函数无参数的情况
        
/// </summary>
        
/// <param name="callback">待执行的托管方法</param>
        
/// <param name="waitFinish">是否等待函数完成</param>

        public static void Invoke(MultiWaitCallback callback,bool waitFinish)
        
{
            Invoke(callback,waitFinish,
null);
        }


        
/// <summary>
        
/// 根据服务器的处理器数选择使用线程模式执行托管方法,默认等待函数完成
        
/// </summary>
        
/// <param name="callback">待执行的托管方法</param>
        
/// <param name="Params">函数参数</param>

        public static void Invoke(MultiWaitCallback callback,params object[] Params)
        
{
            Invoke(callback,
true,Params);
        }


        
/// <summary>
        
/// 根据服务器的处理器数选择使用线程模式执行托管方法,默认等待函数完成。适用于托管函数无参数的情况
        
/// </summary>
        
/// <param name="callback"></param>

        public static void Invoke(MultiWaitCallback callback)
        
{
            Invoke(callback,
true);
        }

        
/// <summary>
        
/// 根据服务器的处理器数选择使用线程模式执行托管方法
        
/// </summary>
        
/// <param name="callback">待执行的托管方法</param>
        
/// <param name="waitFinish">是否等待函数完成</param>
        
/// <param name="Params">函数参数</param>
        
/// <returns>被托管函数的返回值</returns>

        public static object Invoke(WithReturnMultiWaitCallback callback,bool waitFinish,params object[] Params)
        
{
            
return Invoke((object)callback,waitFinish,Params);
        }


        
/// <summary>
        
/// 根据服务器的处理器数选择使用线程模式执行托管方法。适用于托管函数无参数的情况
        
/// </summary>
        
/// <param name="callback">待执行的托管方法</param>
        
/// <param name="waitFinish">是否等待函数完成</param>
        
/// <returns>被托管函数的返回值</returns>

        public static object Invoke(WithReturnMultiWaitCallback callback,bool waitFinish)
        
{
            
return Invoke(callback,waitFinish,null);
        }


        
/// <summary>
        
/// 根据服务器的处理器数选择使用线程模式执行托管方法,默认等待函数完成
        
/// </summary>
        
/// <param name="callback">待执行的托管方法</param>
        
/// <param name="Params">函数参数</param>
        
/// <returns>被托管函数的返回值</returns>

        public static object Invoke(WithReturnMultiWaitCallback callback,params object[] Params)
        
{
            
return Invoke(callback,true,Params);
        }


        
/// <summary>
        
/// 根据服务器的处理器数选择使用线程模式执行托管方法,默认等待函数完成。适用于托管函数无参数的情况
        
/// </summary>
        
/// <param name="callback">待执行的托管方法</param>
        
/// <returns>被托管函数的返回值</returns>

        public static object Invoke(WithReturnMultiWaitCallback callback)
        
{
            
return Invoke(callback,true);
        }

        
private static void ProcThread(object state)
        
{
            ThreadState threadState
=state as ThreadState;
            
if(threadState!=null)
            
{
                
lock(threadState.SynRoot)
                
{
                    Monitor.Pulse(threadState.SynRoot);
                    MultiWaitCallback callback
=threadState.Callback as MultiWaitCallback;
                    
if(callback!=null)
                    
{
                        callback.Method.Invoke(callback.Target ,
new object[]{new ArrayList((Array)threadState.Parameter).ToArray() } ) ;
                    }

                    
else
                    
{
                        WithReturnMultiWaitCallback withReturnCallback
= threadState.Callback as WithReturnMultiWaitCallback;
                        threadState.ReturnValue 
=withReturnCallback.Method.Invoke(withReturnCallback.Target ,new object[]{new ArrayList((Array)threadState.Parameter).ToArray() }) ;
                    }

                }

            }


        }

        
private class ThreadState
        
{
            
private string _id;
            
private object _returnValue;
            
private object _parameter;
            
private object _synRoot=new object() ;
            
private object _callback;
            
/// <summary>
            
/// 构造函数
            
/// </summary>
            
/// <param name="threadId">线程编号</param>

            public ThreadState(string threadId)
            
{
                
if(threadId==null||threadId.Trim().Length ==0 )
                
{
                    _id
=Guid.NewGuid().ToString() ;
                }

                _id
=threadId;
            }


            
/// <summary>
            
/// 获取线程编号
            
/// </summary>

            public string ThreadId
            
{
                
get
                
{
                    
return _id;
                }

            }


            
/// <summary>
            
/// 获取或设置线程返回值
            
/// </summary>

            public object ReturnValue
            
{
                
get
                
{
                    
return _returnValue;
                }

                
set
                
{
                    _returnValue
=value;
                }

            }


            
/// <summary>
            
/// 获取或设置线程参数
            
/// </summary>

            public object Parameter
            
{
                
get
                
{
                    
return _parameter;
                }

                
set
                
{
                    _parameter
=value;
                }

            }


            
/// <summary>
            
/// 线程同步锁
            
/// </summary>

            public object SynRoot
            
{
                
get
                
{
                    
return _synRoot;
                }

            }


            
public object Callback
            
{
                
get
                
{
                    
return _callback;
                }

                
set
                
{
                    _callback
=value;
                }

            }

        
        }


    }

在这个Class中会自动判断服务器的处理器个数,如果是单CPU的处理器就不会使用多线程的模型,因为这样不但不会提高效率反而会增加系统对多线程管理的负担。如果使用多CPU的话自然会创建新的线程,而在这里重要的一点就是线程同步,大部分函数执行的过程中都需要返回值,或者需要等待过程执行完成。
而在使用的过程中,需要为每一个操作过程写两个函数,一个用来提供外部接口(public),另外一个用来实际执行数据处理。如下面的程序

        
/// <summary>
        
/// 在事务中删除数据实体。
        
/// </summary>
        
/// <param name="entity">数据实体,不能为null。</param>
        
/// <param name="broker">事务处理对象,不能为null。</param>
        
/// <returns>是否删除成功</returns>

        public static bool DeleteEntity(PublicCodeItemEntity entity, DbBroker broker)
        
{
            
return (bool)ThreadManager.Invoke(new WithReturnMultiWaitCallback(ProcDeleteEntityWithBroker),entity,broker) ;
        }


        
private static object ProcDeleteEntityWithBroker(params object[] Params)
        
{
            PublicCodeItemEntity entity
=Params[0as PublicCodeItemEntity;
            DbBroker broker
=Params[1as DbBroker;
            broker.TransactionCommit 
+=new BrokerTransactionEventHandler(broker_TransactionCommit);
            
bool res = broker.ExecuteNonQuery(PublicCodeItemDataAccess.GetDeleteEntity(entity)) > 0;
            
return res;
        }

可能在上面的实现方法上还有很多的不足之处,希望大家能够不吝赐教。

posted on 2005-07-20 08:48  Edward.Net  阅读(2543)  评论(3编辑  收藏  举报

导航