Is # Threading Patterns a good idea?

Today I played with my project and found an interesting small fragment, given the following template, you can safely clear the stream, even if it forced to close earlier. My project is a network server on which a new thread is created for each client. I found this useful for early termination from the remote side, but also from the local side (I can just call .Abort()inside my processing code).

Are there any problems you can see with this, or any suggestions you would make to anyone looking for a similar approach?

The following is a test case:


using System;
using System.Threading;

class Program
{
    static Thread t1 = new Thread(thread1);
    static Thread t2 = new Thread(thread2);

    public static void Main(string[] args)
    {
        t1.Start();
        t2.Start();
        t1.Join();
    }

    public static void thread1() {
        try {
            // Do our work here, for this test just look busy.
            while(true) {
                Thread.Sleep(100);
            }
        } finally {
            Console.WriteLine("We're exiting thread1 cleanly.\n");
            // Do any cleanup that might be needed here.
        }
    }

    public static void thread2() {
        Thread.Sleep(500);
        t1.Abort();
    }
}

For reference, without a try / finally block, the thread just dies, as you might expect.

+3
3

- , . . - ASP.NET ThreadAbortException, , , - .

- , , . .

+14

, "" , , . , . , . .

  • , Thread.Abort. , , , . , thread2.
  • , finally, . finally, , .
  • , finally, lock'd .

, . , , .

+3

It is generally not recommended to stop threads. What you can do is poll for the stopRequested flag, which can be set from other threads. The following is an example WorkerThread class for your reference. For more information on how to use it, refer to http://devpinoy.org/blogs/jakelite/archive/2008/12/20/threading-patterns-the-worker-thread-pattern.aspx

public abstract class WorkerThreadBase : IDisposable
{
    private Thread _workerThread;
    protected internal ManualResetEvent _stopping;
    protected internal ManualResetEvent _stopped;
    private bool _disposed;
    private bool _disposing;
    private string _name;

    protected WorkerThreadBase()
        : this(null, ThreadPriority.Normal)
    {
    }

    protected WorkerThreadBase(string name)
        : this(name, ThreadPriority.Normal)
    {
    }

    protected WorkerThreadBase(string name,
        ThreadPriority priority)
        : this(name, priority, false)
    {
    }

    protected WorkerThreadBase(string name,
        ThreadPriority priority,
        bool isBackground)
    {
        _disposing = false;
        _disposed = false;
        _stopping = new ManualResetEvent(false);
        _stopped = new ManualResetEvent(false);

        _name = name == null ? GetType().Name : name; ;
        _workerThread = new Thread(threadProc);
        _workerThread.Name = _name;
        _workerThread.Priority = priority;
        _workerThread.IsBackground = isBackground;
    }

    protected bool StopRequested
    {
        get { return _stopping.WaitOne(1, true); }
    }

    protected bool Disposing
    {
        get { return _disposing; }
    }

    protected bool Disposed
    {
        get { return _disposed; }
    }

    public string Name
    {
        get { return _name; }            
    }   

    public void Start()
    {
        ThrowIfDisposedOrDisposing();
        _workerThread.Start();
    }

    public void Stop()
    {
        ThrowIfDisposedOrDisposing();
        _stopping.Set();
        _stopped.WaitOne();
    }

    public void WaitForExit()
    {
        ThrowIfDisposedOrDisposing();            
        _stopped.WaitOne();
    }

    #region IDisposable Members

    public void Dispose()
    {
        dispose(true);
    }

    #endregion

    public static void WaitAll(params WorkerThreadBase[] threads)
    { 
        WaitHandle.WaitAll(
            Array.ConvertAll<WorkerThreadBase, WaitHandle>(
                threads,
                delegate(WorkerThreadBase workerThread)
                { return workerThread._stopped; }));
    }

    public static void WaitAny(params WorkerThreadBase[] threads)
    {
        WaitHandle.WaitAny(
            Array.ConvertAll<WorkerThreadBase, WaitHandle>(
                threads,
                delegate(WorkerThreadBase workerThread)
                { return workerThread._stopped; }));
    }

    protected virtual void Dispose(bool disposing)
    {
        //stop the thread;
        Stop();

        //make sure the thread joins the main thread
        _workerThread.Join(1000);

        //dispose of the waithandles
        DisposeWaitHandle(_stopping);
        DisposeWaitHandle(_stopped);
    }

    protected void ThrowIfDisposedOrDisposing()
    {
        if (_disposing)
        {
            throw new InvalidOperationException(
                Properties.Resources.ERROR_OBJECT_DISPOSING);
        }

        if (_disposed)
        {
            throw new ObjectDisposedException(
                GetType().Name,
                Properties.Resources.ERROR_OBJECT_DISPOSED);
        }
    }

    protected void DisposeWaitHandle(WaitHandle waitHandle)
    {
        if (waitHandle != null)
        {
            waitHandle.Close();
            waitHandle = null;
        }
    }

    protected abstract void Work();

    private void dispose(bool disposing)
    {
        //do nothing if disposed more than once
        if (_disposed)
        {
            return;
        }

        if (disposing)
        {
            _disposing = disposing;

            Dispose(disposing);

            _disposing = false;
            //mark as disposed
            _disposed = true;
        }
    }

    private void threadProc()
    {
        Work();
        _stopped.Set();
    }        
}
0
source

Source: https://habr.com/ru/post/1703993/


All Articles