简体   繁体   中英

C# background thread worker

I am trying to read data from my USB buffer. However when I read data from the buffer I have to perform some operation on this data, and this takes time. In the mean time the external device observes that the buffer is full and stops writing data. I need to overcome this situation. THe processing involves reading the array and some UI operations , so I though I could put the entire operation of reading data into a background thread and read the data once the background thread has completed operation

BackgroundWorker bw = new BackgroundWorker();

        // this allows our worker to report progress during work
        bw.WorkerReportsProgress = true;

        // what to do in the background thread
        bw.DoWork += new DoWorkEventHandler(
        delegate(object o, DoWorkEventArgs args)
        {
            BackgroundWorker b = o as BackgroundWorker;

            // do some simple processing for 10 seconds
            for (int i = 1; i <= 10; i++)
            {
                // report the progress in percent
                b.ReportProgress(i * 10);
                Thread.Sleep(1000);
            }
           //I have to keep reading from the buffer here


        });

        // what to do when progress changed (update the progress bar for example)
        bw.ProgressChanged += new ProgressChangedEventHandler(
        delegate(object o, ProgressChangedEventArgs args)
        {
            label1.Text = string.Format("{0}% Completed", args.ProgressPercentage);
        });

        // what to do when worker completes its task (notify the user)
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
        delegate(object o, RunWorkerCompletedEventArgs args)
        {
            label1.Text = "Finished!";
             //I have to use the data from the buffer here
        });

        bw.RunWorkerAsync();

But even with this approach I still am not reading the buffer continously since only after the operation on the UI completes can I call the background worker again. Is there any way to continously read the buffer(like into a large 2d array) and keep notifying me when each 1d array of the buffer is full? The main idea is the task in the worker should not be stopped, however I still need to get the data from the worker task(know that it has completed). What would be the best way to achieve this?

Maybe in your case using the following class would come handy :

    public class BackgroundTimer : BackgroundWorker
    {
        private ManualResetEvent intervalManualReset;
        private enum ProcessStatus { Created, Running, JobCompleted, ExceptionOccured };
        private ProcessStatus processStatus = new ProcessStatus();

        public int Interval { get; set; }
        public BackgroundTimer()
        {
            this.processStatus = ProcessStatus.Created;
            this.WorkerSupportsCancellation = true;
            this.Interval = 1000;
        }

        protected override void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
        {
            base.OnRunWorkerCompleted(e);
            if (processStatus == ProcessStatus.ExceptionOccured)
                // Log : Process stopped;
                processStatus = ProcessStatus.JobCompleted;
        }
        protected override void OnDoWork(DoWorkEventArgs e)
        {
            while (!this.CancellationPending)
            {
                try
                {
                    base.OnDoWork(e);
                    this.Sleep();
                }
                catch (Exception exception)
                {
                    //Log excepption;
                    this.processStatus = ProcessStatus.ExceptionOccured;
                    this.Stop();
                }
            }
            if (e != null)
                e.Cancel = true;
        }

        public void Start()
        {
            this.processStatus = ProcessStatus.Running;
            if (this.IsBusy)
                return;

            this.intervalManualReset = new ManualResetEvent(false);
            this.RunWorkerAsync();
        }
        public void Stop()
        {
            this.CancelAsync();
            this.WakeUp();
            this.Dispose(true);
        }
        public void WakeUp()
        {
            if (this.intervalManualReset != null)
                this.intervalManualReset.Set();
        }
        private void Sleep()
        {
            if (this.intervalManualReset != null)
            {
                this.intervalManualReset.Reset();
                this.intervalManualReset.WaitOne(this.Interval);
            }
        }
        public void Activate()
        {
            if (!this.IsBusy)
                // Log : Process activated.
                this.Start();
        }
    }

EDIT : Usage :

        private void InitializeThread()
        {
            var timer = new BackgroundTimer();
            timer.Interval = 1000; // sleep 1 second between each iteration.
            timer.DoWork += timer_DoWork;
            timer.Start();
        }

        void timer_DoWork(object sender, DoWorkEventArgs e)
        {
            // your desired operation.
        }

I hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM