protected override StdSharedPtr <StdVector <StdSharedPtr <UserDatum> > > WorkProducer()
        {
            try
            {
                // Close program when empty frame
                if (this._ImageFiles.Length <= this._Counter)
                {
                    OpenPose.Log("Last frame read and added to queue. Closing program after it is processed.", Priority.High);
                    // This funtion stops this worker, which will eventually stop the whole thread system once all the
                    // frames have been processed
                    this.Stop();
                    return(null);
                }
                else
                {
                    // Create new datum
                    var vector    = new StdVector <StdSharedPtr <UserDatum> >();
                    var datumsPtr = new StdSharedPtr <StdVector <StdSharedPtr <UserDatum> > >(vector);
                    datumsPtr.Get().EmplaceBack();
                    var datum = datumsPtr.Get().At(0);

                    // C# cannot set pointer object by using assignment operator
                    datum.Reset(new UserDatum());

                    // Fill datum
                    using (var cvInputData = Cv.ImRead(this._ImageFiles[this._Counter++]))
                        using (var inputData = OpenPose.OP_CV2OPCONSTMAT(cvInputData))
                            datum.Get().CvInputData = inputData;

                    // If empty frame -> return nullptr
                    if (datum.Get().CvInputData.Empty)
                    {
                        OpenPose.Log($"Empty frame detected on path: {this._ImageFiles[this._Counter - 1]}. Closing program.", Priority.High);
                        this.Stop();
                        datumsPtr = null;
                    }

                    return(datumsPtr);
                }
            }
            catch (Exception e)
            {
                OpenPose.Log("Some kind of unexpected error happened.");
                this.Stop();
                OpenPose.Error(e.Message, -1, nameof(this.WorkProducer));
                return(null);
            }
        }
        public StdSharedPtr <StdVector <StdSharedPtr <Datum> > > CreateDatum()
        {
            // Close program when empty frame
            if (this._Closed || this._ImageFiles.Length <= this._Counter)
            {
                OpenPose.Log("Last frame read and added to queue. Closing program after it is processed.", Priority.High);

                // This funtion stops this worker, which will eventually stop the whole thread system once all the
                // frames have been processed
                this._Closed = true;
                return(null);
            }
            else
            {
                // Create new datum
                var vector    = new StdVector <StdSharedPtr <Datum> >();
                var datumsPtr = new StdSharedPtr <StdVector <StdSharedPtr <Datum> > >(vector);
                datumsPtr.Get().EmplaceBack();
                var datum = datumsPtr.Get().At(0);

                // C# cannot set pointer object by using assignment operator
                datum.Reset(new Datum());

                // Fill datum
                using (var cvInputData = Cv.ImRead(this._ImageFiles[this._Counter++]))
                    using (var inputData = OpenPose.OP_CV2OPCONSTMAT(cvInputData))
                        datum.Get().CvInputData = inputData;

                // If empty frame -> return nullptr
                if (datum.Get().CvInputData.Empty)
                {
                    OpenPose.Log($"Empty frame detected on path: {this._ImageFiles[this._Counter - 1]}. Closing program.", Priority.High);
                    this._Closed = true;
                    datumsPtr    = null;
                }

                return(datumsPtr);
            }
        }