Click here to Skip to main content
15,910,872 members
Home / Discussions / C#
   

C#

 
QuestionBackgroundWorker.IsBusy failure!? Pin
Chesnokov Yuriy22-May-10 23:32
professionalChesnokov Yuriy22-May-10 23:32 
AnswerRe: BackgroundWorker.IsBusy failure!? Pin
DaveyM6923-May-10 0:58
professionalDaveyM6923-May-10 0:58 
QuestionRe: BackgroundWorker.IsBusy failure!? Pin
Chesnokov Yuriy23-May-10 1:32
professionalChesnokov Yuriy23-May-10 1:32 
AnswerRe: BackgroundWorker.IsBusy failure!? Pin
DaveyM6923-May-10 2:10
professionalDaveyM6923-May-10 2:10 
AnswerRe: BackgroundWorker.IsBusy failure!? Pin
Chesnokov Yuriy23-May-10 4:04
professionalChesnokov Yuriy23-May-10 4:04 
GeneralRe: BackgroundWorker.IsBusy failure!? Pin
DaveyM6923-May-10 4:24
professionalDaveyM6923-May-10 4:24 
GeneralRe: BackgroundWorker.IsBusy failure!? Pin
Luc Pattyn23-May-10 5:09
sitebuilderLuc Pattyn23-May-10 5:09 
AnswerRe: BackgroundWorker.IsBusy failure!? Pin
DaveyM6923-May-10 3:36
professionalDaveyM6923-May-10 3:36 
I said I didn't think it'd be too hard to sync the IsBusy etc. I hate saying that without knowing for sure so I've knocked up a quick version. This should be OK (untested!), but if using other locks or other synchronisation methods in your other code I'd use the MS one. (Needs comments and descriptions adding)
C#
using System;
using System.ComponentModel;
using System.Threading;

namespace DaveyM69.ComponentModel
{
    [DefaultEvent("DoWork")]
    [DefaultProperty("WorkerReportsProgress")]
    public class SaferBackgroundWorker : Component
    {
        public event DoWorkEventHandler DoWork;
        public event ProgressChangedEventHandler ProgressChanged;
        public event RunWorkerCompletedEventHandler RunWorkerCompleted;

        private bool cancellationPending;
        private bool isBusy;
        private AsyncOperation operation;
        private SendOrPostCallback operationCompleted;
        private SendOrPostCallback progressReporter;
        private object syncLock = new object();
        private bool workerReportsProgress;
        private bool workerSupportsCancellation;
        private ParameterizedThreadStart workerThreadStart;

        public SaferBackgroundWorker()
        {
            cancellationPending = false;
            isBusy = false;
            operation = null;
            operationCompleted = new SendOrPostCallback(OperationCompleted);
            progressReporter = new SendOrPostCallback(ProgressReporter);
            workerReportsProgress = false;
            workerSupportsCancellation = false;
            workerThreadStart = new ParameterizedThreadStart(WorkerThreadStart);
        }

        [Browsable(false)]
        public bool CancellationPending
        {
            get { lock (syncLock) { return cancellationPending; } }
        }
        [Browsable(false)]
        public bool IsBusy
        {
            get { lock (syncLock) { return isBusy; } }
        }
        [DefaultValue(false)]
        public bool WorkerReportsProgress
        {
            get { lock (syncLock) { return workerReportsProgress; } }
            set { lock (syncLock) { workerReportsProgress = value; } }
        }
        [DefaultValue(false)]
        public bool WorkerSupportsCancellation
        {
            get { lock (syncLock) { return workerSupportsCancellation; } }
            set { lock (syncLock) { workerSupportsCancellation = value; } }
        }

        public void CancelAsync()
        {
            if (!WorkerSupportsCancellation)
                throw new InvalidOperationException("Worker doesn't support cancellation");
            SetCancellationPending(true);
        }
        protected virtual void OnDoWork(DoWorkEventArgs e)
        {
            DoWorkEventHandler eh = DoWork;
            if (eh != null)
                eh(this, e);
        }
        protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
        {
            ProgressChangedEventHandler eh = ProgressChanged;
            if (eh != null)
                eh(this, e);
        }
        protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
        {
            RunWorkerCompletedEventHandler eh = RunWorkerCompleted;
            if (eh != null)
                eh(this, e);
        }
        private void OperationCompleted(object state)
        {
            SetIsBusy(false);
            SetCancellationPending(false);
            OnRunWorkerCompleted((RunWorkerCompletedEventArgs)state);
        }
        private void ProgressReporter(object state)
        {
            OnProgressChanged((ProgressChangedEventArgs)state);
        }
        public void ReportProgress(int percentProgress)
        {
            ReportProgress(percentProgress, null);
        }
        public void ReportProgress(int percentProgress, object userState)
        {
            if (!WorkerReportsProgress)
                throw new InvalidOperationException("Worker doesn't report progress");
            ProgressChangedEventArgs arg = new ProgressChangedEventArgs(percentProgress, userState);
            if (operation == null)
                progressReporter(arg);
            else
                operation.Post(progressReporter, arg);
        }
        public void RunWorkerAsync()
        {
            RunWorkerAsync(null);
        }
        public void RunWorkerAsync(object argument)
        {
            if (IsBusy)
                throw new InvalidOperationException("Worker is busy");
            SetIsBusy(true);
            SetCancellationPending(false);
            operation = AsyncOperationManager.CreateOperation(null);
            workerThreadStart.BeginInvoke(argument, null, null);
        }
        private void SetCancellationPending(bool value)
        {
            lock (syncLock) { cancellationPending = value; }
        }
        private void SetIsBusy(bool value)
        {
            lock (syncLock) { isBusy = value; }
        }
        private void WorkerThreadStart(object obj)
        {
            object result = null;
            Exception error = null;
            bool cancelled = false;
            try
            {
                DoWorkEventArgs doWorkArgs = new DoWorkEventArgs(obj);
                OnDoWork(doWorkArgs);
                if (doWorkArgs.Cancel)
                    cancelled = true;
                else
                    result = doWorkArgs.Result;
            }
            catch (Exception exception)
            {
                error = exception;
            }
            RunWorkerCompletedEventArgs e = new RunWorkerCompletedEventArgs(result, error, cancelled);
            operation.PostOperationCompleted(operationCompleted, e);
        }
    }
}

Dave

If this helped, please vote & accept answer!


Binging is like googling, it just feels dirtier. (Pete O'Hanlon)

BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

AnswerRe: BackgroundWorker.IsBusy failure!? Pin
Luc Pattyn23-May-10 2:24
sitebuilderLuc Pattyn23-May-10 2:24 
GeneralRe: BackgroundWorker.IsBusy failure!? Pin
Chesnokov Yuriy23-May-10 3:55
professionalChesnokov Yuriy23-May-10 3:55 
GeneralRe: timer ticks overlap [modified] Pin
Luc Pattyn23-May-10 4:23
sitebuilderLuc Pattyn23-May-10 4:23 
QuestionPreventing DataGridView column from auto-resizing when double-clicking the column header divider Pin
eyalbi00722-May-10 22:23
eyalbi00722-May-10 22:23 
QuestionAnybody? Please, I'm so stuck here... Pin
eyalbi00723-May-10 3:53
eyalbi00723-May-10 3:53 
AnswerHave a little patience... Pin
OriginalGriff23-May-10 4:34
mveOriginalGriff23-May-10 4:34 
QuestionRe: Preventing DataGridView column from auto-resizing when double-clicking the column header divider Pin
nicos2817-Oct-11 3:03
nicos2817-Oct-11 3:03 
QuestionPlz help me Pin
dia 201022-May-10 22:04
dia 201022-May-10 22:04 
AnswerRe: Plz help me Pin
Abhinav S22-May-10 22:20
Abhinav S22-May-10 22:20 
Generalthis chunck of code have same results Pin
dia 201023-May-10 1:26
dia 201023-May-10 1:26 
AnswerRe: Plz help me Pin
Not Active23-May-10 3:38
mentorNot Active23-May-10 3:38 
Generalgetting ip address of client on server side Pin
dia 201023-May-10 18:53
dia 201023-May-10 18:53 
QuestionHow to include in installer Access Database 2003.? Pin
joynil22-May-10 17:51
joynil22-May-10 17:51 
AnswerRe: How to include in installer Access Database 2003.? Pin
PIEBALDconsult23-May-10 7:08
mvePIEBALDconsult23-May-10 7:08 
QuestionWhats iS THE Problem Of MY code in Monitor class For Resolve of Race Condition Pin
shahramkeyboard22-May-10 11:26
shahramkeyboard22-May-10 11:26 
AnswerRe: Whats iS THE Problem Of MY code in Monitor class For Resolve of Race Condition Pin
Luc Pattyn22-May-10 11:49
sitebuilderLuc Pattyn22-May-10 11:49 
Questionuse of ? and : [Solved] Pin
William Winner22-May-10 11:22
William Winner22-May-10 11:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.