Reputation: 1591
I have 4 classes that perform different actions, each of the 2 tasks should run syncronously.
My current implementation works fine, but sometimes there are strange lags and some of the processors
do not run. This could be the threads issue I suppose.
I would like to refactor the code to use Hangfire library or any other way to keep the program working correctly. I'm not sure how to property do that and would appreciate any help.
public void Run()
{
var processors1 = new CommonProcessor[] { new AProcessor(), new BProcessor() };
//AProcessor should be first!
var processors2 = new CommonProcessor[] { new CProcessor(), new DProcessor() };
//CProcessor should be first!
Task task1 = Task.Run(() => RunSyncProcess(processors1);
Task task2 = Task.Run(() => RunSyncProcess(processors2);
Task.WaitAll(task1, task2);
}
private void RunSyncProcess(CommonProcessor[] processors)
{
while (true)
{
foreach (var processor in processors)
{
// do some job
}
Thread.Sleep(frequency);
}
}
Upvotes: 0
Views: 1786
Reputation: 705
Hangfire is primarily used for fire and forget tasks where you can queue, schedule and requeue jobs, if thats what you want to achieve you can install via nuget and then use the following syntax
BackgroundJob.Enqueue(() => RunSyncProcess(processors1));
so in order to refactor your code you would need to decide whether you want to schedule a job or whether you want to wait for a successful completion of a previous task prior to waiting for a new task, really depends on what you want to achieve.
public void Run()
{
var processors1 = new CommonProcessor[] { new AProcessor(), new BProcessor() };
//AProcessor should be first!
var processors2 = new CommonProcessor[] { new CProcessor(), new DProcessor() };
//CProcessor should be first!
BackgroundJob.Enqueue(() => RunSyncProcess(processors1));
BackgroundJob.Enqueue(() => RunSyncProcess(processors2));
}
public void RunSyncProcess(CommonProcessor[] processors)
{
while (true)
{
foreach (var processor in processors)
{
// do some job
}
}
}
You won't have to await all as these will kick of behind the scene and your UI will be responsive. Remember that the methods will need to be public when you want to use hangfire.
Upvotes: 1
Reputation: 2357
You are using Tasks the wrong way. Tasks are supposed to be non blocking or short term lived items.
Basically what happens here is that you launch Tasks which never end and never release their thread. This will result in blocking some threads of the ThreadPool.
There are multiple way to change things:
1) Non blocking tasks:
public void Run()
{
var processors1 = new CommonProcessor[] { new AProcessor(), new BProcessor() };
//AProcessor should be first!
var processors2 = new CommonProcessor[] { new CProcessor(), new DProcessor() };
//CProcessor should be first!
Task task1 = RunSyncProcess(processors1);
Task task2 = RunSyncProcess(processors2);
Task.WhenAll(task1, task2);
}
private async Task RunSyncProcess(CommonProcessor[] processors)
{
while (true)
{
foreach (var processor in processors)
{
// do some job
}
await Task.Delay(TimeSpan.FromMilliseconds(frequency));//will free threadpool while waiting
}
}
2) Using blocking threads but without impacting threadpool:
public void Run()
{
var processors1 = new CommonProcessor[] { new AProcessor(), new BProcessor() };
//AProcessor should be first!
var processors2 = new CommonProcessor[] { new CProcessor(), new DProcessor() };
//CProcessor should be first!
Thread t1 = new Thread(() => RunSyncProcess(processors1));
t1.Start();
Thread t2 = new Thread(() => RunSyncProcess(processors1));
t2.Start();
t1.Join();
t2.Join();
}
private void RunSyncProcess(CommonProcessor[] processors)
{
while (true)
{
foreach (var processor in processors)
{
// do some job
}
Thread.Sleep(frequency);
}
}
Upvotes: 1