Search code examples
c#backgroundworker

Passing a method to a BackgroundWorker.DoEvent C#


I am currently trying to make a regular function run as an anonymous BackgroundWorker's DoWork event. The issue I have is that the method is not running at all. The current code I have is as follows;-

public class Worker
{
    BackgroundWorker worker;
    public Worker(Func<bool> action)
    {
        worker = new BackgroundWorker();
        worker.DoWork += (sender, e) => e.Result = action;
        worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        this.action = action;
    }

    private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("Thread completed : "+ e.Result.ToString());
    }

    public void DoWork()
    {
        Console.WriteLine("worker thread: working...");
        worker.RunWorkerAsync();
        //Wait for worker to complete
        do { } while (worker.IsBusy);
    }
}

The function is passed like this:-

Worker workerObject = new Worker(new Func<bool>(() => methodThatReturnsBool(param1, param2)));
Thread workerThread = new Thread(workerObject.DoWork);

workerThread.Start();

How is it possible to pass the method and have it run within the background worker?


Solution

  • From the looks of it, you are just assigning the action itself as a result, instead of calling it.

    worker.DoWork += (sender, e) => e.Result = action();
    

    Also the waiting loop might cause problems. At least put a

    do {Thread.Yield();} while (worker.IsBusy);
    

    in there

    Or use a cleaner (no busy-waiting) approach:

    public class Worker
    {
        private BackgroundWorker _worker;
        private AutoResetEvent _event;
        private Func<bool> _action;
    
        public Worker(Func<bool> action)
        {
            _action = action;
            _event = new AutoResetEvent(false);
            _worker = new BackgroundWorker();
            _worker.DoWork += (sender, e) => 
            {
                try
                {
                    e.Result = _action();
                }
                finally
                {
                    _event.Set();
                }
            };
            _worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        }
    
        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Console.WriteLine("Thread completed : "+ e.Result.ToString());
        }
    
        public void DoWork()
        {
            Console.WriteLine("worker thread: working...");
            _worker.RunWorkerAsync();
            _event.WaitOne();
        }
    }