I'm having some problems trying to understand how exactly Func works in C#, despite having read a handful og good blogposts about it.
I have the following scenario: I'm building a small billing system which uses the Azure Service Bus queue to process billings. There's two processes that can be initialized by the user:
For this, I've made a general method which initializes a billing task (containing N billings) which takes a bool parameter to tell if it's a daybook or actual billings that needs to be created. Inside this method, I'm running the following check:
if (isDayBookProcessing)
{
// Daybook processing code here
}
else
{
// Run queue process async
StartQueueProcess(queueName, billingTaskId, numOfItemsEnqueued);
}
I've then got a general "StartQueueProcess" method, which is run in it's own Task like this:
private void StartQueueProcess(string queueName, int billingTaskId, int numOfItemsEnqueued)
{
Task.Factory.StartNew(() => _factory.AzureFactory.ServiceBus.ProcessBillingQueue(queueName, billingTaskId, numOfItemsEnqueued));
}
As you can see, the StartQueueProcess method runs the ProcessBillingQueue method on m y ServiceBusclass, which means that it can't run a ProcessDaybookQueue
What I initially thought was to just make use of Func<string, int, int, bool> and make StartQueueProcessmethod return a bool (since Func needs to return something) making it look like this:
if (isDayBookProcessing)
{
// Daybook processing code here
StartQueueProcess(_factory.AzureFactory.ServiceBus.ProcessDaybookQueue(queueName, billingTaskId, numOfItemsEnqueued));
}
else
{
// Run queue process async
StartQueueProcess(_factory.AzureFactory.ServiceBus.ProcessBillingQueue(queueName, billingTaskId, numOfItemsEnqueued));
}
private bool StartQueueProcess(Func<string, int, int, bool> processMethod)
{
Task.Factory.StartNew(() => processMethod);
return true;
}
However, this gives an error telling me that Argument type 'void' is not assignable to parameter type 'System.Func<string, int, int bool>'
My _factory.AzureFactory.ServiceBus.ProcessDaybookQueue(queueName, billingTaskId, numOfItemsEnqueued) returns void. Making it return Func<string, int, int, bool> gives no errors. But why exactly? Shouldn't I be able to make it return what I want (i.e. void)?
Can anyone shed some light on this? :-)
You don't need a Func, you need an Action. A Func is when your delegate has a return value. An Action is fit when there is no return value:
private void StartQueueProcess(Action<string, int, int> processMethod)
{
Task.Factory.StartNew(() => processMethod);
}
Note, that wrapping async over sync is an anti-pattern. You're better off using Task.Run at the call-site instead:
if (isDayBookProcessing)
{
// Daybook processing code here
Task.Run(() => _factory.AzureFactory.ServiceBus.ProcessDaybookQueue(
queueName,
billingTaskId,
numOfItemsEnqueued));
}
else
{
// Run queue process async
Task.Run(() => _factory.AzureFactory.ServiceBus.ProcessBillingQueue(
queueName,
billingTaskId,
numOfItemsEnqueued));
}
Although I see you're invoking the same method, so I don't see the need for an if-else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With