在启动当前线程上下文的线程上调用方法

时间:2013-10-12 18:34:32

标签: c# .net multithreading locking

我有一个类,它使用名为Start / Stop的方法启动/终止一个线程。 Stop方法正确清理线程资源但如果线程本身自然终止或异常终止,我需要能够调用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));
    }
}

2 个答案:

答案 0 :(得分:2)

如果你不想像Mike建议的那样在一个单独的“维护”线程中跟踪你的ThreadStates,你可以试试这个:

在Process方法中保留break语句以退出while循环(和锁定上下文)。在方法的最后添加此代码:

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

一旦线程池有一个可用线程(通常是立即),它就会使用线程池调用实例中的Stop方法。

编辑: 您还可以向Stop方法添加一个参数,该参数表示您只想清理资源,而不进行任何线程同步(因为线程无论如何都要退出)。或者更好,将现有方法拆分为两个:清理和停止。这允许您在不使用线程池的情况下在Process方法的末尾调用Stop(Cleanup)。

答案 1 :(得分:0)

在主类中设置一个计时器,用于检查其管理的每个线程的ThreadState。如果状态为ThreadState.Stopped,请继续清理(并将其从线程集合中删除以进行监视)。