1

Start/Stop というメソッドを使用してスレッドを起動/終了するクラスがあります。Stop メソッドは Threading リソースを適切にクリーンアップしますが、スレッド自体が自然終了または例外で終了した場合は、適切にクリーンアップするために Stop または別のバリエーション (必要な場合) を呼び出せる必要があります。

スレッド メソッド内から Stop を呼び出すことは、私が用意したロック メカニズムのため、オプションではありません。

元のコンテキストで Stop メソッドを呼び出す方法はありますか?

private bool Terminate { get; set; }
private object _SyncRoot = new object();
private System.Threading.Thread Thread { get; set; }
private System.Threading.CancellationTokenSource CancellationTokenSource { get; set; }

public bool Start (ProcessorOptions options)
{
    bool result = false;

    lock (this._SyncRoot)
    {
        if (this.State == EnumState.Ready)
        {
            this.Options = options;

            if (this.CancellationTokenSource != null)
            {
                this.CancellationTokenSource.Dispose();
            }

            this.CancellationTokenSource = new System.Threading.CancellationTokenSource();
            //this.CancellationTokenSource.Token.Register(?, null, true);

            this.Terminate = false;

            this.Thread = new System.Threading.Thread(new System.Threading.ThreadStart(this.Process));
            this.Thread.Start();

            result = true;
        }
    }

    return (result);
}

public void Stop ()
{
    lock (this._SyncRoot)
    {
        if (this.State == EnumState.Processing)
        {
            try
            {
                this.Terminate = true;
                this.CancellationTokenSource.Cancel(false);

                if (!this.Thread.Join(System.TimeSpan.FromSeconds(1.0D)))
                {
                    this.Thread.Abort();
                }
            }
            finally
            {
                this.Thread = null;
            }
        }
    }
}

private void Process ()
{
    lock (this._SyncRoot)
    {
        if (this.State != EnumState.Ready)
        {
            throw (new System.InvalidOperationException("The processor instance is not in a ready state."));
        }
    }

    while (!this.Terminate)
    {
        lock (this._SyncRoot)
        {
            if (this.QueuedDocuments.Count == 0)
            {
                if (this.StopAutomaticallyOnQueueEmpty)
                {
                    // Invoke this.Stop() before breaking.
                    break;
                }
            }
        }

        // Parallel.For uses CancellationTokenSource here.

        System.Threading.Thread.Sleep(System.TimeSpan.FromSeconds(0.2D));
    }
}
4

2 に答える 2

2

マイクが提案したように、別の「メンテナンス」スレッドで ThreadStates を追跡したくない場合は、これを試すことができます。

Process メソッドに break ステートメントを保持して、while ループを終了します (およびコンテキストをロックします)。メソッドの最後に次のコードを追加します。

ThreadPool.QueueUserWorkItem(o => Stop());

これは、スレッドプールに使用可能なスレッドができるとすぐに (通常はすぐに)、スレッドプールを使用してインスタンスの Stop メソッドを呼び出します。

編集:リソースをクリーンアップするだけで、スレッド同期を行わないことを通知するパラメータをStopメソッドに追加することもできます(スレッドはとにかく終了しようとしているため)。または、既存のメソッドをクリーンアップと停止の 2 つに分割することをお勧めします。これにより、スレッド プールを使用せずに、Process メソッドの最後で Stop (Cleanup) を呼び出すことができます。

于 2013-10-12T19:59:03.073 に答える