Delen via


Inleiding tot threads voor serviceobjectlezers (POS voor .NET v1.14 SDK-documentatie)

De meeste serviceobjecten moeten asynchroon kunnen reageren op hardware-gebeurtenissen door een afzonderlijke thread met hardwarelezers te starten. Serviceobjecten zijn de koppeling tussen de Point of Service-toepassing en de hardware. Serviceobjecten moeten daarom gegevens lezen van de bijbehorende hardware terwijl ze nog steeds beschikbaar zijn voor de toepassing.

In deze sectie ziet u een manier om de code te implementeren die nodig is voor multithreaded Service-objecten.

Vereisten

Als u deze code wilt compileren, moet de toepassing een verwijzing naar de System.Threading-naamruimte bevatten.

In het onderstaande voorbeeld wordt een threading-helperklasse geïmplementeerd die kan worden gebruikt door serviceobject-implementaties, maar niet zelfstandig wordt gecompileerd of uitgevoerd.

Demonstreert

In dit voorbeeld ziet u hoe serviceobjecten threading kunnen gebruiken om het asynchroon bewaken van hardwaregebeurtenissen te ondersteunen. De voorbeeldcode implementeert een thread-helperklasse die kan worden gebruikt om basisthreadingondersteuning toe te voegen aan een serviceobject.

Als u de thread-helperklasse in deze sectie wilt gebruiken, moet u een klasse maken die is afgeleid van ServiceObjectThreadHelper, die is opgenomen in de onderstaande code en de volgende methoden implementeren:

  • ServiceObjectThreadOpen Deze methode wordt aangeroepen vanuit de OpenThread-methode van de thread-helperklasse nadat de initialisatie is voltooid. Implementeer hier hardwarespecifieke initialisatiecode. Deze methode is virtueel. De standaard implementatie retourneert gewoon.

  • ServiceObjectThreadClose Deze methode wordt aangeroepen wanneer het thread-helperobject de thread beëindigt of wanneer de methode Verwijderen wordt aangeroepen en moet worden gebruikt om onbeheerde ingangen of andere resources met betrekking tot het apparaat vrij te geven. Deze methode is virtueel. De standaard implementatie retourneert gewoon.

  • ServiceObjectProcedure Deze methode wordt aangeroepen zodra alle initialisatie heeft plaatsgevonden en de thread is gestart. Deze methode is abstract en moet worden geïmplementeerd in de klasse die is afgeleid van de thread-helperklasse. De methode ServiceObjectProcedure heeft één argument, een ManualEvent-ingang . De threadprocedure moet worden afgesloten wanneer deze ingang is ingesteld. Dit wordt gedaan door ManualEvent.WaitOne binnen een tijdje lus aan te roepen. Voorbeeld:

    
        while (true)
        {
            // Wait for a hardware event or the thread stop event.
    
            // Test to see if the thread terminated event is set and
            // exit the thread if so.
            if (ThreadStopEvent.WaitOne(0, false))
            {
               break;
            }
    
            // The thread is not terminating, so it must be a
            // a hardware event.
        }
    

Voorbeeld

using System;
using System.Threading;
using Microsoft.PointOfService;

namespace Samples.ServiceObjects.Advanced
{
    // The following code implements a thread helper class.
    // This class may be used by other Point Of Service
    // samples which may require a separate thread for monitoring
    // hardware.
    public abstract class ServiceObjectThreadHelper : IDisposable
    {
        // The thread object which will wait for data from the POS
        // device.
        private Thread ReadThread;

        // These events signal that the thread is starting or stopping.
        private AutoResetEvent ThreadTerminating;
        private AutoResetEvent ThreadStarted;

        // Keeps track of whether or not a thread should
        // be running.
        bool ThreadWasStarted;

        public ServiceObjectThreadHelper()
        {
            // Create events to signal the reader thread.
            ThreadTerminating = new AutoResetEvent(false);
            ThreadStarted = new AutoResetEvent(false);

            ThreadWasStarted = false;

            // You need to handle the ApplicationExit event so
            // that you can properly clean up the thread.
            System.Windows.Forms.Application.ApplicationExit +=
                        new EventHandler(Application_ApplicationExit);
        }

        ~ServiceObjectThreadHelper()
        {
            Dispose(true);
        }

        public virtual void ServiceObjectThreadOpen()
        {
            return;
        }

        public virtual void ServiceObjectThreadClose()
        {
            return;
        }

        // This is called when the thread starts successfully and
        // will be run on the new thread.
        public abstract void ServiceObjectThreadProcedure(
                AutoResetEvent ThreadStopEvent);

        private bool IsDisposed = false;
        protected virtual void Dispose(bool disposing)
        {
            if (!IsDisposed)
            {
                try
                {
                    if (disposing == true)
                    {
                        CloseThread();
                    }
                }
                finally
                {
                    IsDisposed = true;
                }
            }
        }

        public void Dispose()
        {
            Dispose(true);

            // This object has been disposed of, so no need for
            // the GC to call the finalization code again.
            GC.SuppressFinalize(this);
        }

        public void OpenThread()
        {
            try
            {
                // Check to see if this object is still valid.
                if (IsDisposed)
                {
                    // Throw system exception to indicate that
                        // the object has already been disposed.
                    throw new ObjectDisposedException(
                            "ServiceObjectSampleThread");
                }

                // In case the application has called OpenThread
                // before calling CloseThread, stop any previously
                // started thread.
                SignalThreadClose();

                ServiceObjectThreadOpen();

                // Reset event used to signal the thread to quit.
                ThreadTerminating.Reset();

                // Reset the event that used by the thread to signal
                // that it has started.
                ThreadStarted.Reset();

                // Create the thread object and give it a name. The
                // method used here, ThreadMethod, is a wrapper around
                // the actual thread procedure, which will be run in
                // the threading object provided by the Service
                // Object.
                ReadThread = new Thread(
                        new ThreadStart(ThreadMethod));

                // Set the thread background mode.
                ReadThread.IsBackground = false;

                // Finally, attempt to start the thread.
                ReadThread.Start();

                // Wait for the thread to start, or until the time-out
                // is reached.
                if (!ThreadStarted.WaitOne(3000, false))
                {
                    // If the time-out was reached before the event
                    // was set, then throw an exception.
                    throw new PosControlException(
                            "Unable to open the device for reading",
                            ErrorCode.Failure);
                }

                // The thread has started successfully.
                ThreadWasStarted = true;
            }
            catch (Exception e)
            {
                // If an error occurred, be sure the new thread is
                // stopped.
                CloseThread();

                // Re-throw to let the application handle the
                // failure.
                throw;
            }
        }

        private void SignalThreadClose()
        {
            if(ThreadTerminating != null && ThreadWasStarted)
            {
                // Tell the thread to terminate.
                ThreadTerminating.Set();

                // Give the thread a few seconds to end.
                ThreadStarted.WaitOne(10000, false);

                // Mark the thread as being terminated.
                ThreadWasStarted = false;
            }
        }

        public void CloseThread()
        {
            // Signal the thread that it should stop.
            SignalThreadClose();

            // Call back into the SO for any cleanup.
            ServiceObjectThreadClose();
        }

        private void Application_ApplicationExit(
                            object sender,
                            EventArgs e)
        {
            SignalThreadClose();
        }

        // This is the method run on the new thread. First it signals
        // the caller indicating that the thread has started
        // correctly. Next, it calls the service object's thread
        // method which will loop waiting for data or a signal
        // to close.
        private void ThreadMethod()
        {
            try
            {
                // Set the event to indicate that the thread has
                // started successfully.
                ThreadStarted.Set();

                // Call into the thread procedure defined by the
                // Service Object.
                ServiceObjectThreadProcedure(ThreadTerminating);

                // Signal that the thread procedure is exiting.
                ThreadStarted.Set();
            }
            catch (Exception e)
            {
                Logger.Info("ServiceObjectThreadHelper",
                        "ThreadMethod Exception = " + e.ToString());
                throw;
            }
        }
    }
}

Zie ook

Opdrachten

Meer informatie