0

ThreadManagerアプリケーション中に作成されたスレッドを処理するオブジェクトを作成しようとしています。

全体の目的は、メインFormを閉じる前にスレッドを終了し、その終了時間中に新しいスレッドを作成できないようにすることです。ご覧のとおり、スレッド作成コード全体と内部にもロックを適用していますAllowNewThreads

2つ以上の新しいスレッドがロックを待機することがあると確信しています。これはそれほど悪いことではありません、わずかな遅延が発生する可能性があります。より良い結果を得るために、またはおそらく私がまだ検討していない別の戦略を得るために、ロック配置の別の代替案がありますか?

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
}
4

1 に答える 1

1

コメントで述べたように、スレッドがジョブで完了するまで待つだけです。したがって、スレッドを手動で管理する代わりに を使用できますThreadPool。これは、有効期間が短いジョブの場合ははるかに効率的であるためです。長時間実行されるタスクのTask場合、.NET 3.5 で使用できるクラス (キャンセルをサポートしています!) を使用します (Rx がサポートしていると思いますが、もっと簡単な方法があるかもしれません)。

スレッドは非常に重いオブジェクトであり、その管理はアプリの扱いにくい部分になる可能性があります。


また、ロック オブジェクト (編集前) に関するコメントです。アプリケーション全体で、スレッドがロックできるオブジェクトがクラスごとに 1 つだけであることを確認する必要があります。そうしないと、厄介なバグが発生します。

于 2012-07-16T15:11:21.100 に答える