Consumer Producer- Producer thread never executes assigned function
I have .NET Core Web API solution. In each call, I need to perform some database operations.
The issue is at a time multiple db connections get opened & close. So to avoid it, I want to implement Queue of objects to be sent to database and then want a separate thread to perform db operation.
I've tried some code as below. But here, Consumer thread never executes assigned function. There is no separate thread for Producer, I am simply feeding queue with object.
What modifications I should do? Need some guidance as I'm new to Threading stuff.
public static class BlockingQueue
{
public static Queue<WebServiceLogModel> queue;
static BlockingQueue()
{
queue = new Queue<WebServiceLogModel>();
}
public static object Dequeue()
{
lock (queue)
{
while (queue.Count == 0)
{
Monitor.Wait(queue);
}
return queue.Dequeue();
}
}
public static void Enqueue(WebServiceLogModel webServiceLog)
{
lock (queue)
{
queue.Enqueue(webServiceLog);
Monitor.Pulse(queue);
}
}
public static void ConsumerThread(IConfiguration configuration)
{
WebServiceLogModel webServiceLog = (WebServiceLogModel)Dequeue();
webServiceLog.SaveWebServiceLog(configuration);
}
public static void ProducerThread(WebServiceLogModel webServiceLog)
{
Enqueue(webServiceLog);
Thread.Sleep(100);
}
}
I've created and started thread in StartUp.cs:
public Startup(IConfiguration configuration)
{
Thread t = new Thread(() => BlockingQueue.ConsumerThread(configuration));
t.Start();
}
In Controller, I've written code to feed the queue:
[HttpGet]
[Route("abc")]
public IActionResult GetData()
{
BlockingQueue.ProducerThread(logModel);
return StatusCode(HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound, ApplicationConstants.Message.NoBatchHistoryInfo);
}
c# multithreading .net-core queue thread-synchronization
add a comment |
I have .NET Core Web API solution. In each call, I need to perform some database operations.
The issue is at a time multiple db connections get opened & close. So to avoid it, I want to implement Queue of objects to be sent to database and then want a separate thread to perform db operation.
I've tried some code as below. But here, Consumer thread never executes assigned function. There is no separate thread for Producer, I am simply feeding queue with object.
What modifications I should do? Need some guidance as I'm new to Threading stuff.
public static class BlockingQueue
{
public static Queue<WebServiceLogModel> queue;
static BlockingQueue()
{
queue = new Queue<WebServiceLogModel>();
}
public static object Dequeue()
{
lock (queue)
{
while (queue.Count == 0)
{
Monitor.Wait(queue);
}
return queue.Dequeue();
}
}
public static void Enqueue(WebServiceLogModel webServiceLog)
{
lock (queue)
{
queue.Enqueue(webServiceLog);
Monitor.Pulse(queue);
}
}
public static void ConsumerThread(IConfiguration configuration)
{
WebServiceLogModel webServiceLog = (WebServiceLogModel)Dequeue();
webServiceLog.SaveWebServiceLog(configuration);
}
public static void ProducerThread(WebServiceLogModel webServiceLog)
{
Enqueue(webServiceLog);
Thread.Sleep(100);
}
}
I've created and started thread in StartUp.cs:
public Startup(IConfiguration configuration)
{
Thread t = new Thread(() => BlockingQueue.ConsumerThread(configuration));
t.Start();
}
In Controller, I've written code to feed the queue:
[HttpGet]
[Route("abc")]
public IActionResult GetData()
{
BlockingQueue.ProducerThread(logModel);
return StatusCode(HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound, ApplicationConstants.Message.NoBatchHistoryInfo);
}
c# multithreading .net-core queue thread-synchronization
"The issue is at a time multiple db connections get opened & close. So to avoid it" why do you want to do this, do you have a concurrency problem?
– TheGeneral
Nov 21 at 6:56
yes. concurrency issue I am facing. Any suggestions for that?
– Priya
Nov 21 at 6:57
I will check TPL too then, if it is helpful then.
– Priya
Nov 21 at 7:03
Two suggestions, firstly don't make the object you are using as a lock public. It's hard enough to make sure that you don't deadlock something without allowing other objects to join the party. Secondly, take a look at BlockingCollection which implements a producer consumer pattern for you.
– Adam G
Nov 21 at 7:23
Blocking collection I've heard about. I will check if its helpful in my case. Thanks.
– Priya
Nov 21 at 7:45
add a comment |
I have .NET Core Web API solution. In each call, I need to perform some database operations.
The issue is at a time multiple db connections get opened & close. So to avoid it, I want to implement Queue of objects to be sent to database and then want a separate thread to perform db operation.
I've tried some code as below. But here, Consumer thread never executes assigned function. There is no separate thread for Producer, I am simply feeding queue with object.
What modifications I should do? Need some guidance as I'm new to Threading stuff.
public static class BlockingQueue
{
public static Queue<WebServiceLogModel> queue;
static BlockingQueue()
{
queue = new Queue<WebServiceLogModel>();
}
public static object Dequeue()
{
lock (queue)
{
while (queue.Count == 0)
{
Monitor.Wait(queue);
}
return queue.Dequeue();
}
}
public static void Enqueue(WebServiceLogModel webServiceLog)
{
lock (queue)
{
queue.Enqueue(webServiceLog);
Monitor.Pulse(queue);
}
}
public static void ConsumerThread(IConfiguration configuration)
{
WebServiceLogModel webServiceLog = (WebServiceLogModel)Dequeue();
webServiceLog.SaveWebServiceLog(configuration);
}
public static void ProducerThread(WebServiceLogModel webServiceLog)
{
Enqueue(webServiceLog);
Thread.Sleep(100);
}
}
I've created and started thread in StartUp.cs:
public Startup(IConfiguration configuration)
{
Thread t = new Thread(() => BlockingQueue.ConsumerThread(configuration));
t.Start();
}
In Controller, I've written code to feed the queue:
[HttpGet]
[Route("abc")]
public IActionResult GetData()
{
BlockingQueue.ProducerThread(logModel);
return StatusCode(HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound, ApplicationConstants.Message.NoBatchHistoryInfo);
}
c# multithreading .net-core queue thread-synchronization
I have .NET Core Web API solution. In each call, I need to perform some database operations.
The issue is at a time multiple db connections get opened & close. So to avoid it, I want to implement Queue of objects to be sent to database and then want a separate thread to perform db operation.
I've tried some code as below. But here, Consumer thread never executes assigned function. There is no separate thread for Producer, I am simply feeding queue with object.
What modifications I should do? Need some guidance as I'm new to Threading stuff.
public static class BlockingQueue
{
public static Queue<WebServiceLogModel> queue;
static BlockingQueue()
{
queue = new Queue<WebServiceLogModel>();
}
public static object Dequeue()
{
lock (queue)
{
while (queue.Count == 0)
{
Monitor.Wait(queue);
}
return queue.Dequeue();
}
}
public static void Enqueue(WebServiceLogModel webServiceLog)
{
lock (queue)
{
queue.Enqueue(webServiceLog);
Monitor.Pulse(queue);
}
}
public static void ConsumerThread(IConfiguration configuration)
{
WebServiceLogModel webServiceLog = (WebServiceLogModel)Dequeue();
webServiceLog.SaveWebServiceLog(configuration);
}
public static void ProducerThread(WebServiceLogModel webServiceLog)
{
Enqueue(webServiceLog);
Thread.Sleep(100);
}
}
I've created and started thread in StartUp.cs:
public Startup(IConfiguration configuration)
{
Thread t = new Thread(() => BlockingQueue.ConsumerThread(configuration));
t.Start();
}
In Controller, I've written code to feed the queue:
[HttpGet]
[Route("abc")]
public IActionResult GetData()
{
BlockingQueue.ProducerThread(logModel);
return StatusCode(HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound, ApplicationConstants.Message.NoBatchHistoryInfo);
}
c# multithreading .net-core queue thread-synchronization
c# multithreading .net-core queue thread-synchronization
asked Nov 21 at 6:54
Priya
61151231
61151231
"The issue is at a time multiple db connections get opened & close. So to avoid it" why do you want to do this, do you have a concurrency problem?
– TheGeneral
Nov 21 at 6:56
yes. concurrency issue I am facing. Any suggestions for that?
– Priya
Nov 21 at 6:57
I will check TPL too then, if it is helpful then.
– Priya
Nov 21 at 7:03
Two suggestions, firstly don't make the object you are using as a lock public. It's hard enough to make sure that you don't deadlock something without allowing other objects to join the party. Secondly, take a look at BlockingCollection which implements a producer consumer pattern for you.
– Adam G
Nov 21 at 7:23
Blocking collection I've heard about. I will check if its helpful in my case. Thanks.
– Priya
Nov 21 at 7:45
add a comment |
"The issue is at a time multiple db connections get opened & close. So to avoid it" why do you want to do this, do you have a concurrency problem?
– TheGeneral
Nov 21 at 6:56
yes. concurrency issue I am facing. Any suggestions for that?
– Priya
Nov 21 at 6:57
I will check TPL too then, if it is helpful then.
– Priya
Nov 21 at 7:03
Two suggestions, firstly don't make the object you are using as a lock public. It's hard enough to make sure that you don't deadlock something without allowing other objects to join the party. Secondly, take a look at BlockingCollection which implements a producer consumer pattern for you.
– Adam G
Nov 21 at 7:23
Blocking collection I've heard about. I will check if its helpful in my case. Thanks.
– Priya
Nov 21 at 7:45
"The issue is at a time multiple db connections get opened & close. So to avoid it" why do you want to do this, do you have a concurrency problem?
– TheGeneral
Nov 21 at 6:56
"The issue is at a time multiple db connections get opened & close. So to avoid it" why do you want to do this, do you have a concurrency problem?
– TheGeneral
Nov 21 at 6:56
yes. concurrency issue I am facing. Any suggestions for that?
– Priya
Nov 21 at 6:57
yes. concurrency issue I am facing. Any suggestions for that?
– Priya
Nov 21 at 6:57
I will check TPL too then, if it is helpful then.
– Priya
Nov 21 at 7:03
I will check TPL too then, if it is helpful then.
– Priya
Nov 21 at 7:03
Two suggestions, firstly don't make the object you are using as a lock public. It's hard enough to make sure that you don't deadlock something without allowing other objects to join the party. Secondly, take a look at BlockingCollection which implements a producer consumer pattern for you.
– Adam G
Nov 21 at 7:23
Two suggestions, firstly don't make the object you are using as a lock public. It's hard enough to make sure that you don't deadlock something without allowing other objects to join the party. Secondly, take a look at BlockingCollection which implements a producer consumer pattern for you.
– Adam G
Nov 21 at 7:23
Blocking collection I've heard about. I will check if its helpful in my case. Thanks.
– Priya
Nov 21 at 7:45
Blocking collection I've heard about. I will check if its helpful in my case. Thanks.
– Priya
Nov 21 at 7:45
add a comment |
2 Answers
2
active
oldest
votes
First of all, try to avoid static
classes and methods. Use pattern singleton in that case (and if you really need this).
Second, try to avoid lock
, Monitor
- those concurrency primitives significantly lower your performance.
In such situation, you can use BlockingCollection<> as 'Adam G' mentioned above, or you can develop your own solution.
public class Service : IDisposable
{
private readonly BlockingCollection<WebServiceLogModel> _packets =
new BlockingCollection<WebServiceLogModel>();
private Task _task;
private volatile bool _active;
private static readonly TimeSpan WaitTimeout = TimeSpan.FromSeconds(1);
public Service()
{
_active = true;
_task = ExecTaskInternal();
}
public void Enqueue(WebServiceLogModel model)
{
_packets.Add(model);
}
public void Dispose()
{
_active = false;
}
private async Task ExecTaskInternal()
{
while (_active)
{
if (_packets.TryTake(out WebServiceLogModel model))
{
// TODO: whatever you need
}
else
{
await Task.Delay(WaitTimeout);
}
}
}
}
public class MyController : Controller
{
[HttpGet]
[Route("abc")]
public IActionResult GetData([FromServices] Service service)
{
// receive model form somewhere
WebServiceLogModel model = FetchModel();
// enqueue model
service.Enqueue(model);
// TODO: return what you need
}
}
And in Startup:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<Service>();
// TODO: other init staffs
}
}
You even can add Start/Stop methods to the service instead of implementing IDisposable
and start your service in the startup class in the method Configure(IApplicationBuilder app)
.
Hi Igor. Thanks for providing solution. I've implemented with few modification as per my requirements. I have not worked with threads before. So was stuck. Btw, will this work flawlessly if multiple endpoints will try to add WebServiceLog concurrently? Thanks again for help! :)
– Priya
Nov 21 at 13:02
1
According to the documentation: link this class was designed for concurrent access.
– Igor Goyda
Nov 21 at 13:16
add a comment |
I think your consumer thread is executed just once if there is something in the queue and then immediately returns. If you want to have a thread doing work in background, which is started just once, it should never return and should catch all exceptions. Your thread from BlockingQueue.ConsumerThread
is invoked once in Stratup
and returns.
Also please be aware that doing such solution is not safe. ASP.NET doesn't guarantee background threads to be running if there are no requests coming in. Your application pool can recycle (and by default it recycles after 20 minutes of inactivity or every 27 hours), so there is a chance that your background code won't be executed for some queue items.
Also, while it doesn't solve all issues, I would suggest using https://www.hangfire.io/ to do background tasks in ASP.NET server. It has persistence layer, can retry jobs and has simple API's. In your request handler you can push new jobs to Hangfire and then have just 1 job processor thread.
What could be the efficient solution for such issues? I am facing concurrency issue. So want to store object in queue and then want a separate thread to perform db stuff.
– Priya
Nov 21 at 7:06
Ideal and most reliable solution would be to have separate queue (RabbitMQ/ServiceBus etc) and separate service that is not running in ASP.Net (another machine / windows service etc) that will process that queue. Reason: survive app domain restarts, because if you have big queue of tasks in memory and app domain restarts, you lose it all.
– dlxeon
Nov 21 at 7:08
Depending on your situation, good enough solution can be to use HangFire. It will handle for you persistence, thread management, locks etc. You can just push items to it and then it will call your job handler.
– dlxeon
Nov 21 at 7:09
Unfortunately, I won't be able to use any third party solutions n required to solve this issue with help of pure .net concepts. :|
– Priya
Nov 21 at 7:14
Actually, I'm a little bit unsure if concurrent database operations is root cause of issue, because databases are designed to handle lots of queries. But if you do believe that's the case, maybe you can tweak database connection pool settings to allow just 1 connection for whole application docs.microsoft.com/en-us/dotnet/framework/data/adonet/… , but then you should add retries and error handling implementation for every database access, because now it may fail due to timeout/lack of connection available.
– dlxeon
Nov 21 at 7:19
|
show 1 more comment
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53406692%2fconsumer-producer-producer-thread-never-executes-assigned-function%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
First of all, try to avoid static
classes and methods. Use pattern singleton in that case (and if you really need this).
Second, try to avoid lock
, Monitor
- those concurrency primitives significantly lower your performance.
In such situation, you can use BlockingCollection<> as 'Adam G' mentioned above, or you can develop your own solution.
public class Service : IDisposable
{
private readonly BlockingCollection<WebServiceLogModel> _packets =
new BlockingCollection<WebServiceLogModel>();
private Task _task;
private volatile bool _active;
private static readonly TimeSpan WaitTimeout = TimeSpan.FromSeconds(1);
public Service()
{
_active = true;
_task = ExecTaskInternal();
}
public void Enqueue(WebServiceLogModel model)
{
_packets.Add(model);
}
public void Dispose()
{
_active = false;
}
private async Task ExecTaskInternal()
{
while (_active)
{
if (_packets.TryTake(out WebServiceLogModel model))
{
// TODO: whatever you need
}
else
{
await Task.Delay(WaitTimeout);
}
}
}
}
public class MyController : Controller
{
[HttpGet]
[Route("abc")]
public IActionResult GetData([FromServices] Service service)
{
// receive model form somewhere
WebServiceLogModel model = FetchModel();
// enqueue model
service.Enqueue(model);
// TODO: return what you need
}
}
And in Startup:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<Service>();
// TODO: other init staffs
}
}
You even can add Start/Stop methods to the service instead of implementing IDisposable
and start your service in the startup class in the method Configure(IApplicationBuilder app)
.
Hi Igor. Thanks for providing solution. I've implemented with few modification as per my requirements. I have not worked with threads before. So was stuck. Btw, will this work flawlessly if multiple endpoints will try to add WebServiceLog concurrently? Thanks again for help! :)
– Priya
Nov 21 at 13:02
1
According to the documentation: link this class was designed for concurrent access.
– Igor Goyda
Nov 21 at 13:16
add a comment |
First of all, try to avoid static
classes and methods. Use pattern singleton in that case (and if you really need this).
Second, try to avoid lock
, Monitor
- those concurrency primitives significantly lower your performance.
In such situation, you can use BlockingCollection<> as 'Adam G' mentioned above, or you can develop your own solution.
public class Service : IDisposable
{
private readonly BlockingCollection<WebServiceLogModel> _packets =
new BlockingCollection<WebServiceLogModel>();
private Task _task;
private volatile bool _active;
private static readonly TimeSpan WaitTimeout = TimeSpan.FromSeconds(1);
public Service()
{
_active = true;
_task = ExecTaskInternal();
}
public void Enqueue(WebServiceLogModel model)
{
_packets.Add(model);
}
public void Dispose()
{
_active = false;
}
private async Task ExecTaskInternal()
{
while (_active)
{
if (_packets.TryTake(out WebServiceLogModel model))
{
// TODO: whatever you need
}
else
{
await Task.Delay(WaitTimeout);
}
}
}
}
public class MyController : Controller
{
[HttpGet]
[Route("abc")]
public IActionResult GetData([FromServices] Service service)
{
// receive model form somewhere
WebServiceLogModel model = FetchModel();
// enqueue model
service.Enqueue(model);
// TODO: return what you need
}
}
And in Startup:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<Service>();
// TODO: other init staffs
}
}
You even can add Start/Stop methods to the service instead of implementing IDisposable
and start your service in the startup class in the method Configure(IApplicationBuilder app)
.
Hi Igor. Thanks for providing solution. I've implemented with few modification as per my requirements. I have not worked with threads before. So was stuck. Btw, will this work flawlessly if multiple endpoints will try to add WebServiceLog concurrently? Thanks again for help! :)
– Priya
Nov 21 at 13:02
1
According to the documentation: link this class was designed for concurrent access.
– Igor Goyda
Nov 21 at 13:16
add a comment |
First of all, try to avoid static
classes and methods. Use pattern singleton in that case (and if you really need this).
Second, try to avoid lock
, Monitor
- those concurrency primitives significantly lower your performance.
In such situation, you can use BlockingCollection<> as 'Adam G' mentioned above, or you can develop your own solution.
public class Service : IDisposable
{
private readonly BlockingCollection<WebServiceLogModel> _packets =
new BlockingCollection<WebServiceLogModel>();
private Task _task;
private volatile bool _active;
private static readonly TimeSpan WaitTimeout = TimeSpan.FromSeconds(1);
public Service()
{
_active = true;
_task = ExecTaskInternal();
}
public void Enqueue(WebServiceLogModel model)
{
_packets.Add(model);
}
public void Dispose()
{
_active = false;
}
private async Task ExecTaskInternal()
{
while (_active)
{
if (_packets.TryTake(out WebServiceLogModel model))
{
// TODO: whatever you need
}
else
{
await Task.Delay(WaitTimeout);
}
}
}
}
public class MyController : Controller
{
[HttpGet]
[Route("abc")]
public IActionResult GetData([FromServices] Service service)
{
// receive model form somewhere
WebServiceLogModel model = FetchModel();
// enqueue model
service.Enqueue(model);
// TODO: return what you need
}
}
And in Startup:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<Service>();
// TODO: other init staffs
}
}
You even can add Start/Stop methods to the service instead of implementing IDisposable
and start your service in the startup class in the method Configure(IApplicationBuilder app)
.
First of all, try to avoid static
classes and methods. Use pattern singleton in that case (and if you really need this).
Second, try to avoid lock
, Monitor
- those concurrency primitives significantly lower your performance.
In such situation, you can use BlockingCollection<> as 'Adam G' mentioned above, or you can develop your own solution.
public class Service : IDisposable
{
private readonly BlockingCollection<WebServiceLogModel> _packets =
new BlockingCollection<WebServiceLogModel>();
private Task _task;
private volatile bool _active;
private static readonly TimeSpan WaitTimeout = TimeSpan.FromSeconds(1);
public Service()
{
_active = true;
_task = ExecTaskInternal();
}
public void Enqueue(WebServiceLogModel model)
{
_packets.Add(model);
}
public void Dispose()
{
_active = false;
}
private async Task ExecTaskInternal()
{
while (_active)
{
if (_packets.TryTake(out WebServiceLogModel model))
{
// TODO: whatever you need
}
else
{
await Task.Delay(WaitTimeout);
}
}
}
}
public class MyController : Controller
{
[HttpGet]
[Route("abc")]
public IActionResult GetData([FromServices] Service service)
{
// receive model form somewhere
WebServiceLogModel model = FetchModel();
// enqueue model
service.Enqueue(model);
// TODO: return what you need
}
}
And in Startup:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<Service>();
// TODO: other init staffs
}
}
You even can add Start/Stop methods to the service instead of implementing IDisposable
and start your service in the startup class in the method Configure(IApplicationBuilder app)
.
answered Nov 21 at 9:38
Igor Goyda
2313
2313
Hi Igor. Thanks for providing solution. I've implemented with few modification as per my requirements. I have not worked with threads before. So was stuck. Btw, will this work flawlessly if multiple endpoints will try to add WebServiceLog concurrently? Thanks again for help! :)
– Priya
Nov 21 at 13:02
1
According to the documentation: link this class was designed for concurrent access.
– Igor Goyda
Nov 21 at 13:16
add a comment |
Hi Igor. Thanks for providing solution. I've implemented with few modification as per my requirements. I have not worked with threads before. So was stuck. Btw, will this work flawlessly if multiple endpoints will try to add WebServiceLog concurrently? Thanks again for help! :)
– Priya
Nov 21 at 13:02
1
According to the documentation: link this class was designed for concurrent access.
– Igor Goyda
Nov 21 at 13:16
Hi Igor. Thanks for providing solution. I've implemented with few modification as per my requirements. I have not worked with threads before. So was stuck. Btw, will this work flawlessly if multiple endpoints will try to add WebServiceLog concurrently? Thanks again for help! :)
– Priya
Nov 21 at 13:02
Hi Igor. Thanks for providing solution. I've implemented with few modification as per my requirements. I have not worked with threads before. So was stuck. Btw, will this work flawlessly if multiple endpoints will try to add WebServiceLog concurrently? Thanks again for help! :)
– Priya
Nov 21 at 13:02
1
1
According to the documentation: link this class was designed for concurrent access.
– Igor Goyda
Nov 21 at 13:16
According to the documentation: link this class was designed for concurrent access.
– Igor Goyda
Nov 21 at 13:16
add a comment |
I think your consumer thread is executed just once if there is something in the queue and then immediately returns. If you want to have a thread doing work in background, which is started just once, it should never return and should catch all exceptions. Your thread from BlockingQueue.ConsumerThread
is invoked once in Stratup
and returns.
Also please be aware that doing such solution is not safe. ASP.NET doesn't guarantee background threads to be running if there are no requests coming in. Your application pool can recycle (and by default it recycles after 20 minutes of inactivity or every 27 hours), so there is a chance that your background code won't be executed for some queue items.
Also, while it doesn't solve all issues, I would suggest using https://www.hangfire.io/ to do background tasks in ASP.NET server. It has persistence layer, can retry jobs and has simple API's. In your request handler you can push new jobs to Hangfire and then have just 1 job processor thread.
What could be the efficient solution for such issues? I am facing concurrency issue. So want to store object in queue and then want a separate thread to perform db stuff.
– Priya
Nov 21 at 7:06
Ideal and most reliable solution would be to have separate queue (RabbitMQ/ServiceBus etc) and separate service that is not running in ASP.Net (another machine / windows service etc) that will process that queue. Reason: survive app domain restarts, because if you have big queue of tasks in memory and app domain restarts, you lose it all.
– dlxeon
Nov 21 at 7:08
Depending on your situation, good enough solution can be to use HangFire. It will handle for you persistence, thread management, locks etc. You can just push items to it and then it will call your job handler.
– dlxeon
Nov 21 at 7:09
Unfortunately, I won't be able to use any third party solutions n required to solve this issue with help of pure .net concepts. :|
– Priya
Nov 21 at 7:14
Actually, I'm a little bit unsure if concurrent database operations is root cause of issue, because databases are designed to handle lots of queries. But if you do believe that's the case, maybe you can tweak database connection pool settings to allow just 1 connection for whole application docs.microsoft.com/en-us/dotnet/framework/data/adonet/… , but then you should add retries and error handling implementation for every database access, because now it may fail due to timeout/lack of connection available.
– dlxeon
Nov 21 at 7:19
|
show 1 more comment
I think your consumer thread is executed just once if there is something in the queue and then immediately returns. If you want to have a thread doing work in background, which is started just once, it should never return and should catch all exceptions. Your thread from BlockingQueue.ConsumerThread
is invoked once in Stratup
and returns.
Also please be aware that doing such solution is not safe. ASP.NET doesn't guarantee background threads to be running if there are no requests coming in. Your application pool can recycle (and by default it recycles after 20 minutes of inactivity or every 27 hours), so there is a chance that your background code won't be executed for some queue items.
Also, while it doesn't solve all issues, I would suggest using https://www.hangfire.io/ to do background tasks in ASP.NET server. It has persistence layer, can retry jobs and has simple API's. In your request handler you can push new jobs to Hangfire and then have just 1 job processor thread.
What could be the efficient solution for such issues? I am facing concurrency issue. So want to store object in queue and then want a separate thread to perform db stuff.
– Priya
Nov 21 at 7:06
Ideal and most reliable solution would be to have separate queue (RabbitMQ/ServiceBus etc) and separate service that is not running in ASP.Net (another machine / windows service etc) that will process that queue. Reason: survive app domain restarts, because if you have big queue of tasks in memory and app domain restarts, you lose it all.
– dlxeon
Nov 21 at 7:08
Depending on your situation, good enough solution can be to use HangFire. It will handle for you persistence, thread management, locks etc. You can just push items to it and then it will call your job handler.
– dlxeon
Nov 21 at 7:09
Unfortunately, I won't be able to use any third party solutions n required to solve this issue with help of pure .net concepts. :|
– Priya
Nov 21 at 7:14
Actually, I'm a little bit unsure if concurrent database operations is root cause of issue, because databases are designed to handle lots of queries. But if you do believe that's the case, maybe you can tweak database connection pool settings to allow just 1 connection for whole application docs.microsoft.com/en-us/dotnet/framework/data/adonet/… , but then you should add retries and error handling implementation for every database access, because now it may fail due to timeout/lack of connection available.
– dlxeon
Nov 21 at 7:19
|
show 1 more comment
I think your consumer thread is executed just once if there is something in the queue and then immediately returns. If you want to have a thread doing work in background, which is started just once, it should never return and should catch all exceptions. Your thread from BlockingQueue.ConsumerThread
is invoked once in Stratup
and returns.
Also please be aware that doing such solution is not safe. ASP.NET doesn't guarantee background threads to be running if there are no requests coming in. Your application pool can recycle (and by default it recycles after 20 minutes of inactivity or every 27 hours), so there is a chance that your background code won't be executed for some queue items.
Also, while it doesn't solve all issues, I would suggest using https://www.hangfire.io/ to do background tasks in ASP.NET server. It has persistence layer, can retry jobs and has simple API's. In your request handler you can push new jobs to Hangfire and then have just 1 job processor thread.
I think your consumer thread is executed just once if there is something in the queue and then immediately returns. If you want to have a thread doing work in background, which is started just once, it should never return and should catch all exceptions. Your thread from BlockingQueue.ConsumerThread
is invoked once in Stratup
and returns.
Also please be aware that doing such solution is not safe. ASP.NET doesn't guarantee background threads to be running if there are no requests coming in. Your application pool can recycle (and by default it recycles after 20 minutes of inactivity or every 27 hours), so there is a chance that your background code won't be executed for some queue items.
Also, while it doesn't solve all issues, I would suggest using https://www.hangfire.io/ to do background tasks in ASP.NET server. It has persistence layer, can retry jobs and has simple API's. In your request handler you can push new jobs to Hangfire and then have just 1 job processor thread.
answered Nov 21 at 7:00
dlxeon
1,51289
1,51289
What could be the efficient solution for such issues? I am facing concurrency issue. So want to store object in queue and then want a separate thread to perform db stuff.
– Priya
Nov 21 at 7:06
Ideal and most reliable solution would be to have separate queue (RabbitMQ/ServiceBus etc) and separate service that is not running in ASP.Net (another machine / windows service etc) that will process that queue. Reason: survive app domain restarts, because if you have big queue of tasks in memory and app domain restarts, you lose it all.
– dlxeon
Nov 21 at 7:08
Depending on your situation, good enough solution can be to use HangFire. It will handle for you persistence, thread management, locks etc. You can just push items to it and then it will call your job handler.
– dlxeon
Nov 21 at 7:09
Unfortunately, I won't be able to use any third party solutions n required to solve this issue with help of pure .net concepts. :|
– Priya
Nov 21 at 7:14
Actually, I'm a little bit unsure if concurrent database operations is root cause of issue, because databases are designed to handle lots of queries. But if you do believe that's the case, maybe you can tweak database connection pool settings to allow just 1 connection for whole application docs.microsoft.com/en-us/dotnet/framework/data/adonet/… , but then you should add retries and error handling implementation for every database access, because now it may fail due to timeout/lack of connection available.
– dlxeon
Nov 21 at 7:19
|
show 1 more comment
What could be the efficient solution for such issues? I am facing concurrency issue. So want to store object in queue and then want a separate thread to perform db stuff.
– Priya
Nov 21 at 7:06
Ideal and most reliable solution would be to have separate queue (RabbitMQ/ServiceBus etc) and separate service that is not running in ASP.Net (another machine / windows service etc) that will process that queue. Reason: survive app domain restarts, because if you have big queue of tasks in memory and app domain restarts, you lose it all.
– dlxeon
Nov 21 at 7:08
Depending on your situation, good enough solution can be to use HangFire. It will handle for you persistence, thread management, locks etc. You can just push items to it and then it will call your job handler.
– dlxeon
Nov 21 at 7:09
Unfortunately, I won't be able to use any third party solutions n required to solve this issue with help of pure .net concepts. :|
– Priya
Nov 21 at 7:14
Actually, I'm a little bit unsure if concurrent database operations is root cause of issue, because databases are designed to handle lots of queries. But if you do believe that's the case, maybe you can tweak database connection pool settings to allow just 1 connection for whole application docs.microsoft.com/en-us/dotnet/framework/data/adonet/… , but then you should add retries and error handling implementation for every database access, because now it may fail due to timeout/lack of connection available.
– dlxeon
Nov 21 at 7:19
What could be the efficient solution for such issues? I am facing concurrency issue. So want to store object in queue and then want a separate thread to perform db stuff.
– Priya
Nov 21 at 7:06
What could be the efficient solution for such issues? I am facing concurrency issue. So want to store object in queue and then want a separate thread to perform db stuff.
– Priya
Nov 21 at 7:06
Ideal and most reliable solution would be to have separate queue (RabbitMQ/ServiceBus etc) and separate service that is not running in ASP.Net (another machine / windows service etc) that will process that queue. Reason: survive app domain restarts, because if you have big queue of tasks in memory and app domain restarts, you lose it all.
– dlxeon
Nov 21 at 7:08
Ideal and most reliable solution would be to have separate queue (RabbitMQ/ServiceBus etc) and separate service that is not running in ASP.Net (another machine / windows service etc) that will process that queue. Reason: survive app domain restarts, because if you have big queue of tasks in memory and app domain restarts, you lose it all.
– dlxeon
Nov 21 at 7:08
Depending on your situation, good enough solution can be to use HangFire. It will handle for you persistence, thread management, locks etc. You can just push items to it and then it will call your job handler.
– dlxeon
Nov 21 at 7:09
Depending on your situation, good enough solution can be to use HangFire. It will handle for you persistence, thread management, locks etc. You can just push items to it and then it will call your job handler.
– dlxeon
Nov 21 at 7:09
Unfortunately, I won't be able to use any third party solutions n required to solve this issue with help of pure .net concepts. :|
– Priya
Nov 21 at 7:14
Unfortunately, I won't be able to use any third party solutions n required to solve this issue with help of pure .net concepts. :|
– Priya
Nov 21 at 7:14
Actually, I'm a little bit unsure if concurrent database operations is root cause of issue, because databases are designed to handle lots of queries. But if you do believe that's the case, maybe you can tweak database connection pool settings to allow just 1 connection for whole application docs.microsoft.com/en-us/dotnet/framework/data/adonet/… , but then you should add retries and error handling implementation for every database access, because now it may fail due to timeout/lack of connection available.
– dlxeon
Nov 21 at 7:19
Actually, I'm a little bit unsure if concurrent database operations is root cause of issue, because databases are designed to handle lots of queries. But if you do believe that's the case, maybe you can tweak database connection pool settings to allow just 1 connection for whole application docs.microsoft.com/en-us/dotnet/framework/data/adonet/… , but then you should add retries and error handling implementation for every database access, because now it may fail due to timeout/lack of connection available.
– dlxeon
Nov 21 at 7:19
|
show 1 more comment
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53406692%2fconsumer-producer-producer-thread-never-executes-assigned-function%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
"The issue is at a time multiple db connections get opened & close. So to avoid it" why do you want to do this, do you have a concurrency problem?
– TheGeneral
Nov 21 at 6:56
yes. concurrency issue I am facing. Any suggestions for that?
– Priya
Nov 21 at 6:57
I will check TPL too then, if it is helpful then.
– Priya
Nov 21 at 7:03
Two suggestions, firstly don't make the object you are using as a lock public. It's hard enough to make sure that you don't deadlock something without allowing other objects to join the party. Secondly, take a look at BlockingCollection which implements a producer consumer pattern for you.
– Adam G
Nov 21 at 7:23
Blocking collection I've heard about. I will check if its helpful in my case. Thanks.
– Priya
Nov 21 at 7:45