Adam Keenan
Adam Keenan

Reputation: 784

Passing function as parameter to create delegate

I'm trying to make a helper function to make BackgroundWorkers.

Here is what I have so far.

using System.ComponentModel;
using System;

public class BackgroundThread {

    BackgroundWorker worker;

    public BackgroundThread(Delegate workerFunction, Delegate workerCallback) {
        this.worker = new BackgroundWorker();
        this.worker.DoWork += new DoWorkEventHandler(workerFunction);
        this.worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workerCallback);
    }

    public void Start(object argument) {
        this.worker.RunWorkerAsync(argument);
    }
}

Although I am getting this error.

Expression denotes a 'variable', where a 'type' or 'method group' was expected

It makes sense since normally you pass a reference to a function to the Handlers but I don't know how to do it in this context. Or is this just not possible. I don't know enough about C# delegates and such to know what to do.

Upvotes: 4

Views: 1230

Answers (2)

Eric
Eric

Reputation: 5743

Like this?

public class BackgroundThread
{

    System.ComponentModel.BackgroundWorker worker;

    public BackgroundThread(System.ComponentModel.DoWorkEventHandler workerFunction, System.ComponentModel.RunWorkerCompletedEventHandler workerCallback)
    {
        this.worker = new System.ComponentModel.BackgroundWorker();
        this.worker.DoWork += workerFunction;
        this.worker.RunWorkerCompleted += workerCallback;
    }

    public BackgroundThread(Action<object> anyWorkFunctionWithObjectArgument, Action<object> anyCallback)
    {
        this.worker = new System.ComponentModel.BackgroundWorker();
        this.worker.DoWork += (sender, e) => { anyWorkFunctionWithObjectArgument.Invoke(e.Argument); };
        this.worker.RunWorkerCompleted += (sender, e) => { anyCallback.Invoke(e.Result); };
    }

    public void Start(object argument)
    {
        this.worker.RunWorkerAsync(argument);
    }

    public static BackgroundThread GetDoNothingInstance()
    {
        return new BackgroundThread(
            (sender, e) =>
            {
                // e is DoWorkEventArgs
            },
            (sender, e) =>
            {
                // e is RunWorkerCompletedEventArgs
            });
    }

    public static BackgroundThread GetDoNothingInstance2()
    {
        Action<object> workfunction = delegate(object argument)
        {
            // Do nothing
        };

        Action<object> callback = delegate(object result) 
        { 
            // Do nothing
        };

        return new BackgroundThread(workfunction, callback);       
    }
}

Upvotes: 3

Sully
Sully

Reputation: 1363

Just saw your comment. This should allow you to just pass a "plain old function" without having to shape it like a handler:

class Program
{
    protected static void plainOldWorkerFunction(object argument)
    {
        return;
    }

    protected static void plainOldCallbackFunction()
    {
        return;
    }

    static void Main(string[] args)
    {
        BackgroundThread bt = new BackgroundThread(plainOldWorkerFunction, plainOldCallbackFunction);

        bt.Start(1234);
    }
}

public class BackgroundThread
{
    BackgroundWorker worker;
    Action<object> workerAction;
    Action callbackAction;

    protected void doWork(object sender, DoWorkEventArgs e)
    {
        workerAction(e.Argument);
    }

    protected void callback(object sender, RunWorkerCompletedEventArgs e)
    {
        callbackAction();
    }

    public BackgroundThread(Action<object> workerFunction, Action workerCallback)
    {
        this.workerAction = workerFunction;
        this.callbackAction = workerCallback;

        this.worker = new BackgroundWorker();
        this.worker.DoWork += doWork;
        this.worker.RunWorkerCompleted += callback;
    }

    public void Start(object argument)
    {
        this.worker.RunWorkerAsync(argument);
    }
}

Original answer:

Try this constructor instead:

public BackgroundThread(DoWorkEventHandler workerFunction, RunWorkerCompletedEventHandler workerCallback)
{
    this.worker = new BackgroundWorker();
    this.worker.DoWork += workerFunction;
    this.worker.RunWorkerCompleted += workerCallback;
}

And just make sure your workerFunction and workerCallback have these parameters:

protected static void workerFunction (object sender, DoWorkEventArgs e)
{
    return;
}

protected static void workerCallback (object sender, RunWorkerCompletedEventArgs e)
{
    return;
}

Upvotes: 2

Related Questions