C#后台线程工作者

时间:2015-08-30 07:13:11

标签: c# arrays multithreading thread-safety

我正在尝试从USB缓冲区读取数据。但是当我从缓冲区读取数据时,我必须对这些数据执行一些操作,这需要时间。同时,外部设备观察到缓冲区已满并停止写入数据。我需要克服这种情况。处理涉及读取数组和一些UI操作,所以我可以将读取数据的整个操作放入后台线程,并在后台线程完成操作后读取数据

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();

但是即使使用这种方法,我仍然没有连续读取缓冲区,因为只有在UI上的操作完成后才能再次调用后台工作程序。有没有办法连续读取缓冲区(比如进入一个大的2d数组)并在缓冲区的每个1d数组满时不断通知我?主要思想是不应该停止worker中的任务,但是我仍然需要从worker任务中获取数据(知道它已经完成)。实现这一目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

也许在你的情况下使用下面的类会很方便:

    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();
        }
    }

编辑:   用法:

        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.
        }

我希望它有所帮助。