在线程管理类中正确放置锁定对象

时间:2012-07-16 13:23:25

标签: c# multithreading locking

我正在尝试创建一个ThreadManager对象来处理在应用程序中创建的线程。

整个目的是在关闭主Form之前终止线程,并且在关闭时间内不允许创建新线程。如您所见,我将锁定应用于整个线程创建代码以及AllowNewThreads内部。

我很确定有时会有两个或更多新线程等待锁定,这不是非常错误,但可能导致小延迟。为了获得更好的结果或者我还没有考虑过另一种策略,是否还有锁定位置的另一种选择?

public class ThreadManager
{
    #region Fields
    private List<Thread> _threads;
    private static Logger _logger = LogManager.GetCurrentClassLogger();
    private static object _lock;
    private bool _allowNewThreads;
    #endregion

    #region Properties

    public bool AllowNewThreads
    {
        get
        {
            return _allowNewThreads;
        }
        set
        {
            lock (_lock)
            {
                _allowNewThreads = value;
            }
        }
    }

    public int CountAlive
    {
        get
        {
            int count = (from t in _threads where (t.IsAlive) select t).Count();
            return count;
        }
    }
    #endregion

    #region Constructors
    private ThreadManager()
    {
        _threads = new List<Thread>();
    }

    public static ThreadManager Instance
    {
        get { return Singleton<ThreadManager>.Instance; }
    }
    #endregion

    #region Methods

    // There must always be thread body in order to create a new thread.
    // Thread parameters are the objects that are needed for calculations etc inside the thread and are optional
    // Start info is the thread itself parameters needed for its creation, such as the thread name, the apartment state 
    // and if it's background or not. That information is optional as well.
    public bool TryAddThread(ParameterizedThreadStart threadBody, object threadParams, ThreadStartInfo startInfo)
    {
        bool success = true;
        try
        {
            lock (_lock)
            {
                if (!AllowNewThreads)
                {
                    throw new Exception("Creation of new threads is denied.");
                }

                Thread f = new Thread(threadBody);

                if (startInfo != null)
                {
                    f.Name = startInfo.Name;
                    f.SetApartmentState(startInfo.ApartmentState);
                    f.IsBackground = startInfo.IsBackground;
                }

                if (threadParams != null)
                {
                    f.Start(threadParams);
                }
                else
                {
                    f.Start();
                }

                _threads.Add(f);
            }
        }
        catch (Exception ex)
        {
            _logger.ErrorException("AddThread", ex);
            success = false;
        }
        return success;
    }
    #endregion
}

1 个答案:

答案 0 :(得分:1)

正如您在评论中提到的那样,您只需等待线程完成该作业。因此,您可以使用ThreadPool而不是手动管理线程,因为它对于短期作业更有效。对于长时间运行的任务,我会使用可用于.NET 3.5的Task类(支持取消!)(我认为Rx支持它,也许有更简单的方法)。

线程是非常重的对象,它们的管理可能会成为您应用的棘手部分。

<小时/> 还有一个关于锁定对象的注释(在编辑之前),你应该尝试确保在线程可以锁定的整个应用程序中每个类只有一个对象,否则你会得到令人讨厌的错误。