Thread for every queue in dictionary c# - multithreading

I have a dictionary with a custom class object as key and a class queue
ConcurrentDictionary<clsEFTOPConnection, Queue<clsEFTOPS>>();
here clsEFTOPConnection and clsEFTOPS are custom classes. I add a new queue if it is not in the dictionary. Now I want to work parallelly on each queue. I want each queue to be watched by threads and whenever a enqueue operation is performed, the particular thread should awake if sleeping and start dequeuing items. So no of threads is equal to no of queues and each thread will act as a watcher of its queue.
I have written below code to achieve it, but it's not functioning as per my needs
public Queue<clsEFTOPS> CheckAlreadyExistingQueue(clsEFTOPConnection objEFTOPConnection, clsEFTOPS objJobQ)
{
Queue<clsEFTOPS> queue;
// See if we have a queue
if (!mHostQueues.TryGetValue(objEFTOPConnection, out queue))
{
// No queue for this Host, so create and cache
queue = new Queue<clsEFTOPS>();
objJobQ.Host = objEFTOPConnection.Host;
objJobQ.PortNo = objEFTOPConnection.PortNo;
objEFTOPConnection.socket_ = objJobQ.ReconnectSocket();
queue.Enqueue(objJobQ);
mHostQueues.TryAdd(objEFTOPConnection, queue);
JobThrd = new Thread(() => DequeueJobs(queue, objEFTOPConnection));
if (JobThrd.ThreadState != ThreadState.Running)
JobThrd.Start();
}
else
{
queue.Enqueue(objJobQ);
if (queue.Count > 1)
JobThrd = new Thread(() => DequeueJobs(queue, objEFTOPConnection));
else
DequeueJobs(queue, objEFTOPConnection);
if (JobThrd.ThreadState != ThreadState.Running)
JobThrd.Start();
}
return queue;
}

Related

Sleep ThreadPoolExecutor threads until interruption

This is a sample batch processing application. Initially I do create a thread pool for the batch processing and then execute those threads on the batching. Once the batch processing is started, it is keep looping and searching for entries in the queue for batching. That is a huge performance drain and the CPU usage goes to max.
The following block contains the sample code, I am currently working on.
BlockingQueue<BatchRequestEntry> batchingQueue;
ThreadPoolExecutor executorService executorService;
private boolean isRunning = false;
private ExecutorService getExecutorService() {
if (executorService == null) {
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("batch-processor-%d").build();
executorService = new ThreadPoolExecutor(batchProcessorConfiguration.getThreadCount(), batchProcessorConfiguration.getThreadCount(),
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(), threadFactory);
}
return executorService;
}
public synchronized void start() {
if (isRunning) {
return;
}
getExecutorService().submit(() -> {
while (isRunning) {
if (!batchingQueue.isEmpty()) {
List<BatchRequestEntry> entries = batchingQueue.batch(batchProcessorConfiguration.getBatchingMaxCount());
executorService.submit(() -> process(entries));
}
}
});
isRunning = true;
}
public SettableFuture<BatchResultEntry> append(BatchRequestEntry batchRequestEntry) {
if (!isRunning) {
start();
}
SettableFuture<BatchResultEntry> future = SettableFuture.create();
batchingQueue.append(batchRequestEntry);
futures.put(batchRequestEntry.getEntryId(), future);
return future;
}
What I want to provide as a solution is to capture the number of loops with empty batching queue. Then compare that value with a threshold value and sleep the threads in the thread pool. Once the new entries are appended to the batching queue, I want to interrupt the thread sleep and continue the loop for batching. I think that would solve the problem.
I want to figure how to do that with ThreadPoolExecutor and I would appreciate if there are better approaches to address this problem. Thank you!

Background Threads and Tasks

I'm trying to find the best way to run a Task from a dedicated background thread.
The context of usage is consuming from a Kafka topic and raising an async event handler to handle the ConsumeResult<TKey, TValue> instance.
A Kafka Consumer (the consumer instance below) blocks the thread until a message is consumed or the CancellationToken it is passed has been cancelled.
consumeThread = new Thread(Consume)
{
Name = "Kafka Consumer Thread",
IsBackground = true,
};
This is the implementation of the Consume method I came up with, which is started by the dedicated thread above:
private void Consume(object _)
{
try
{
while (!cancellationTokenSource.IsCancellationRequested)
{
var consumeResult = consumer.Consume(cancellationTokenSource.Token);
var consumeResultEventArgs = new ConsumeResultReceivedEventArgs<TKey, TValue>(
consumer, consumeResult, cancellationTokenSource.Token);
_ = Task.Run(async () =>
{
if (onConsumeResultReceived is null) continue;
var handlerInstances = onConsumeResultReceived.GetInvocationList();
foreach (ConsumeResultReceivedEventHandler<TKey, TValue> handlerInstance in handlerInstances)
{
if (cancellationTokenSource.IsCancellationRequested) return;
await handlerInstance(this, consumeResultEventArgs).ConfigureAwait(false);
}
}, cancellationTokenSource.Token);
}
}
catch (OperationCanceledException)
{
}
catch (ThreadInterruptedException)
{
}
catch (ThreadAbortException)
{
// Aborting a thread is not implemented in .NET Core.
}
}
I'm not sure this is the recommened way to run a Task from a dedicated Thread, so any advice would be very much appreciated.
It's not clear to me why you need a dedicated thread at all. The code as it currently stands starts a thread and then that thread blocks for consumption and then raises the event handler on a thread pool thread.
The _ = Task.Run idiom is a "fire and forget", which is dangerous in the sense that it will silently swallow any exceptions from your event raising code or event handlers.
I'd recommend replacing Thread with Task.Run, and just raising the event handlers directly:
consumeTask = Task.Run(ConsumeAsync);
private async Task ConsumeAsync()
{
while (true)
{
var consumeResult = consumer.Consume(cancellationTokenSource.Token);
var consumeResultEventArgs = new ConsumeResultReceivedEventArgs<TKey, TValue>(
consumer, consumeResult, cancellationTokenSource.Token);
if (onConsumeResultReceived is null) continue;
var handlerInstances = onConsumeResultReceived.GetInvocationList();
foreach (ConsumeResultReceivedEventHandler<TKey, TValue> handlerInstance in handlerInstances)
{
if (cancellationTokenSource.IsCancellationRequested) return;
await handlerInstance(this, consumeResultEventArgs).ConfigureAwait(false);
}
}
}

Implementation of Queue is not thread safe

I am trying to implement a thread safe queue using a Semaphore that is enqueued with integers. This is not thread-safe at the moment. What would I have to add in terms of synchronization to the queue to make it thread-safe?
I've tried using synchronized blocks on the Queue, so that only one thread is allowed in the queue at the same time, but this does not seem to work, or I am misusing them. What should I be synchronizing on? I have a separate class that is constantly appending and removing with a maintainer thread.
class ThreadSafeQueue {
var queue = List[Int]()
val semaphore = new Semaphore(0)
def append(num: Int): Unit = {
queue = queue ::: List(num)
semaphore.release()
}
def dequeue(): Int = {
semaphore.acquire()
val n = queue.head
queue = queue.tail
n
}
}
To be thread-safe, you should place code that accesses the queue in synchronized blocks, as shown below.
import java.util.concurrent.Semaphore
class ThreadSafeQueue {
var queue = List[Int]()
val semaphore = new Semaphore(0)
def append(num: Int): Unit = {
synchronized {
queue = queue ::: List(num)
}
semaphore.release()
}
def dequeue(): Int = {
semaphore.acquire()
synchronized {
val n = queue.head
queue = queue.tail
n
}
}
}
A few notes:
With the Semaphore permits value set to 0, all acquire() calls will block until there is a release().
In case the Semaphore permits value is > 0, method dequeue would better be revised to return an Option[Int] to cover cases of dequeueing an empty queue.
In case there is only a single queue in your application, consider defining ThreadSafeQueue as object ThreadSafeQueue.
There is an arguably more efficient approach of atomic update using AtomicReference for thread-safety. See this SO link for differences between the two approaches.

Use a Queue to Communicate Between Threads in D

It is easy enough in D to create a Queue type using the std.container.dlist.
I would like to have multiple threads but have them communicate with a queue, not with message passing (https://tour.dlang.org/tour/en/multithreading/message-passing). As I understand it the messages are designed to always receive data at particular points in the code; the receiving thread will block until the expected data is received.
(EDIT: I was informed about receiveTimeout but having a no timeout and just a check is really more appropriate in this case (maybe a timeout of 0?). Also I am not sure what the message API will do if multiple messages are sent before any any are received. I will have to play with that.)
void main() {
spawn(&worker, thisTid);
// This line will block until the expected message is received.
receive (
(string message) {
writeln("Received the message: ", text);
},
)
}
What I am needing is to merely receive data if there is some. Something like this:
void main() {
Queue!string queue// custom `Queue` type based on DList
spawn(&worker, queue);
while (true) {
// Go through any messages (while consuming `queue`)
for (string message; queue) {
writeln("Received a message: ", text);
}
// Do other stuff
}
}
I have tried using shared variables (https://tour.dlang.org/tour/en/multithreading/synchronization-sharing) but DMD is complaining that "Aliases to mutable thread-local data not allowed." or some other errors, depending.
How would this be done in D? Or, is there a way to use messages to do this kind of communication?
This doesn't answer the specific question but ti does clear up what I think is a misunderstanding of the message passing api...
just call receiveTimeout instead of plain receive
http://dpldocs.info/experimental-docs/std.concurrency.receiveTimeout.html
I use this:
shared class Queue(T) {
private T[] queue;
synchronized void opOpAssign(string op)(T object) if(op == "~") {
queue ~= object;
}
synchronized size_t length(){
return queue.length;
}
synchronized T pop(){
assert(queue.length, "Please check queue length, is 0");
auto first = queue[0];
queue = queue[1..$];
return first;
}
synchronized shared(T[]) consume(){
auto copy = queue;
queue = [];
return copy;
}
}
I have gotten the answer I need.
Simply put, use core.thread rather than std.concurrency. std.concurrency manages messages for you and does not allow you to manage it yourself. core.thread is what std.concurrency uses internally.
The longer answer, here is how I fully implemented it.
I have created a Queue type that is based on an Singly Linked List but maintains a pointer of the last element. The Queue also uses standard component inputRange and outputRange (or at least I think it does) per Walter Brights vision (https://www.youtube.com/watch?v=cQkBOCo8UrE).
The Queue is also built to allow one thread to write and another to read with very little mutexing internally so it should be fast.
The Queue I shared here https://pastebin.com/ddyPpLrp
A simple implementation to have a second thread read input:
Queue!string inputQueue = new Queue!string;
ThreadInput threadInput = new ThreadInput(inputQueue);
threadInput.start;
while (true) {
foreach (string value; inputQueue) {
writeln(value);
}
}
ThreadInput being defined as thus:
class ThreadInput : Thread {
private Queue!string queue;
this(Queue!string queue) {
super(&run);
this.queue = queue;
}
private void run() {
while (true) {
queue.put(readln);
}
}
}
The code https://pastebin.com/w5jwRVrL
The Queue again https://pastebin.com/ddyPpLrp

WriteableBitmap in a background worker

I currently have a loop something like this:
foreach(var item in theList)
{
//create writeablebitmap from item.GetPicture() which returns a stream.
//do stuff with it
//save it to isolated storage
}
This is a very long-running process because there are tons of images. I tried putting it in a background worker but you cannot create WriteableBitmaps there (they have to be on the UI thread). The problem is that the interface is totally unresponsive.
How can I make it process keypresses/the UI once every loop, just to make sure it can respond to the user doing things?
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (s, e) =>
{
foreach(var item in theList)
{
var item _ = item;
Deployment.Dispatcher.BeginInvoke(() =>
{
// do your stuff on UI thread with item_
});
Thread.Sleep(milliseconds); //experiment with delay to find balance between UI responsiveness and performance
}
};
backgroundWorker.RunWorkAsync();

Resources