Reputation: 634
I have a generated webapi .NET Core application with a Queue
class that continuously loops through a List<Item>
object where an Item
is a wrapper around a data model and includes some metadata to do some task asynchronously. This Queue
class needs to be accessible in a controller and I have it registered with the DI framework (I think) properly. My issue is that I need for the BeginProcessing
method to begin running when the application starts and for the instance passed to the controller to be the same as the one running the method and I am unsure the best route to go. Any help is appreciated. Anything not included in this context (i.e. Program
, etc. is all pretty much default still.
See Below.
Queue.cs:
public class Queue : IQueue
{
public List<Item> Items { get; set; }
public void BeginProcessing()
{
while(true)
{
if (!(Items.Count < 1))
{
Item Item = Items[0];
if (!Item.Push())
{
Console.WriteLine("Generic Error Message, not final implementation.");
}
Items.Remove(Item);
}
}
}
}
Item.cs
public class Item
{
public SomeDataModel Data { get; set; }
public string Topic { get; set; }
public string Timestamp { get; set; }
public Item(SomeDataModel newData, string newTopic, string newTimestamp)
{
Data = newData;
Topic = newTopic;
Timestamp = newTimestamp;
}
public bool Push()
{
Producer p = new Producer("identifier");
return p.Ingest(Data);
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton<IQueue, Queue>();
}
Upvotes: 0
Views: 3161
Reputation: 634
I ended up finding a solution for my use case without relying on absurd abstraction or some other obscure part of the .NET framework. Whether it is best practice or not, I do not know. But it works and does what I need and at the end of the day, that is what everyone really wants.
My solution:
Register your Singleton in the DI framework, inject the dependency into the Configure
method, then kick off the processing method into another thread.
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton<IQueue, Queue>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IQueue queue)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
Task.Run(() => queue.BeginProcessing());
app.UseHttpsRedirection();
app.UseMvc();
}
Upvotes: 1
Reputation: 1093
You should create some background worker to handle the queue thread.
public void BeginProcessing()
{
while(true)
{
This will catch the calling thread into an infinite loop. Try using a task or backgroundworker. You could even put it inside the queue its self to hide it from the main app.
To start BeginProcessing, from main, get your built container and query for your IQueue. call your IQueue.BeginProcessing() and continue your startup as normal. If everything works as expected, whenever IQueue get's injected into a controller, it will have been the same one you started BeginProcessing on & you should have access to it in a controller context
Upvotes: 1