Is it worth to create new thread per packet handle? - c#

I have a c# server and it has a packet handler that handles packets of clients like this:
for (int i = 0; i < packets.Count; i++)
{
new Thread(new HandlePacket(packets[i].bytes, packets[i].count).handle).Start();
}
Usually the handle packet have lots of code to execute (depands on packet id, sometimes even nested loops), the threads are to prevent hanging (or long execution time) the packet handler because one packet handle can sometimes do nested loop like
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 8; j++)
{
for (int k = 0; k < 32; k++)
{
}
}
}
Is it efficient to do such thing?
If not, what are the alternatives to prevent the hanging of packet handler thread?
The server is for a game, long execution (or hang) time is not acceptable.
Additionally every server have 32 packet handlers (one reserved for each client)

In order to enable data parallelism on the collection, you could make use of the Parallel.ForEach().
Therefore, your code will look something like this:
Parallel.ForEach(packets, (item) =>
{
new HandlePacket(item.bytes, item.count).handle();
});

If you use the Task class you allow the runtime to determine how to use Threads to run your code in parallel.
You would do it like this:
for (int i = 0; i < packets.Count; i++)
{
Task.Run(() => new HandlePacket(packets[i].bytes, packets[i].count).handle).Start());
}
There are some other things you can configure like it, but this will be
much better than starting a thread for each package.

Related

Is there a way of running a single method call using more threads?

I am currently working on a project at my University with trafficlights. I am using SUMO as my simulation program and i have stumbled upon the TraCI libary for controlling the trafficlights.
I have programmed a genetic algorithm, but i have one problem, which in essense, is a bottleneck so small no particle can pass, and that is the simulation program itself.
When controlling multiple clients from the same program (my program) all of the clients run on 2 threads, where in my case i have 8 available. My intention with running the program in multiple threads is, that the program will run faster, since 100 simulations takes roughly 1,5 hours to complete even though i have only simulated about 40 minutes of traffic.
I have posted below the method in which i initialize, start the clients and control them.
The main culprit is probably the two method calls in the last for-loop (the one that control the traffic lights)
So my question is, how can this be parallelized to run on multiple threads, so the program runs faster?
best regards
private async Task RunSimulationAsync()
{
List<TraCIClient> listOfClients = new List<TraCIClient>();
List<SimulationCommands> listOfSimulations = new List<SimulationCommands>();
List<TrafficLightCommands> listOfTrafficLights = new List<TrafficLightCommands>();
//initialize clients, simulationCommands and trafficlightCommands used for controlling sumo
for (int i = 0; i < numberOfInstances; ++i)
{
listOfClients.Add(new TraCIClient());
listOfSimulations.Add(new SimulationCommands(listOfClients[i]));
listOfTrafficLights.Add(new TrafficLightCommands(listOfClients[i]));
}
//open SUMO clients
for (int i = 0; i < numberOfInstances; ++i)
{
OpenSumo(portNumber, sumoOutputFilePath + $"{i}.xml");
await listOfClients[i].ConnectAsync("127.0.0.1", portNumber);
++portNumber;
}
// control trafficlights in simulation
for (int i = 0; i < dnaSize; ++i)
{
for (int j = 0; j < numberOfInstances; j++)
{
listOfTrafficLights[j].SetRedYellowGreenState("n0", $" {Population[j].genes[i]}");
listOfClients[j].Control.SimStep();
}
}
how can this be parallelized to run on multiple threads, so the program runs faster?
First, you need to be sure that the library you're using is capable of being called in a parallel fashion. Not all of them are.
Second, since you have a for index, the most straightforward translation would be to use Parallel.For, e.g.:
for (int i = 0; i < dnaSize; ++i)
{
Parallel.For(0, numberOfInstances, j =>
{
listOfTrafficLights[j].SetRedYellowGreenState("n0", $" {Population[j].genes[i]}");
listOfClients[j].Control.SimStep();
}
}
This will parallelize out to the number of instances.

C# Wait for signals from all the threads before proceed

I'm writing a C# program which involves multithreading and synchronization between multiple threads. The threads all need perform some iterative work independently, and after some thread has finished a specified number of iterations, it must wait for the other threads to come up. After all of them have finished given number of iterations and obtained some intermediate result, they should do some synchronized work and then continue execution again, until another synchronization point is reached and so on.
Here's my attempt to achieve this (a thread should pause after just one iteration, then wait for the others):
int nThreads = Environment.ProcessorCount;
Thread[] threads = new Thread[nThreads];
ManualResetEvent[] manualResetEvents = new ManualResetEvent[nThreads];
for (int i = 0; i < nThreads; i++)
{
manualResetEvents[i] = new ManualResetEvent(false);
}
int nSteps = 5;
Random rnd = new Random();
for (int i = 0; i < nThreads; i++)
{
int idx = i;
threads[i] = new Thread(delegate ()
{
int cStep = nSteps;
while (cStep > 0)
{
manualResetEvents[idx].Reset();
Console.Write("\nThread {0} working... cStep = {1}\n", idx, cStep);
Thread.Sleep(rnd.Next(1000));
manualResetEvents[idx].Set();
Console.WriteLine("\nThread {0} work done. Waiting Others...cStep = {1}\n", idx, cStep);
WaitHandle.WaitAll(manualResetEvents);
cStep--;
}
});
}
for (int i = 0; i < nThreads; i++)
{
threads[i].Start();
}
for (int i = 0; i < nThreads; i++)
{
threads[i].Join();
}
But the code above appears not working, for not any thread waits for all of the other threads to perform one iteration for some reason. I think I misunderstand the purpose of ManualResetEvent or use it the wrong way, what could you suggest?
Your code is prone to race conditions. After all threads have completed the first iteration, all events are still set; if a single thread then runs through the loop before the others get to reset their events, it'll see the other events still set, and stop waiting early.
There's plenty of ways to resolve this bug, but the best solution for you is System.Threading.Barrier (also see Threading objects and features with section about Barrier). It's explicitly designed for this situation, where you want multiple threads to work in parallel through a multi-step algorithm.

C# : How to use Thread and know when exactly thread work is finished?

I read the UNSEEN email in my C# win form project. some times there are attached files, that the downloading make some times, so my project's UI will lock during download complete. Im using ThreadPool for getting solve this problem.
here is my code :
System.Threading.ThreadPool.QueueUserWorkItem((o) =>
{
for (int i = 0; i < lstEmailAddress.Count; i++)
{
Get(imap[i], lstEmailAddress[i].MailBox, out Emails[i]);
}
this.BeginInvoke(new Action(() =>
{
for (int i = 0; i < lstEmailAddress.Count; i++)
{
for (int j = 0; j < Emails[i].Count; j++)
{
Database.EmailRecieve_Insert(Emails[i][j]);
}
arrEmailUserControl[i].txtRecievedCount.Text = (Convert.ToInt32(arrEmailUserControl[i].txtRecievedCount.Text) + Emails[i].Count).ToString();
}
}));
});
here is Get method that I used :
private bool Get(Imap4Client imap, string[,] MailBox, out List<EmailStruct> Emails)
{
Emails = new List<EmailStruct>();
try
{
for (int i = 0; i < MailBox.GetLength(0); i++)
{
Mailbox inbox = imap.SelectMailbox(MailBox[i, 1]);
int[] ids = inbox.Search("UNSEEN");
if (ids.Length > 0)
{
ActiveUp.Net.Mail.Message msg = null;
for (var j = 0; j < ids.Length; j++)
{
msg = inbox.Fetch.MessageObject(ids[j]);
EmailStruct email = new EmailStruct();
email.SourceAddress = msg.From.Email;
email.Subject = msg.Subject;
email.Text = msg.BodyText.Text.ToString();
msg.Attachments.StoreToFolder(InternalConstant.AttachmentFolder);
email.MailBoxID = Convert.ToInt32(MailBox[i, 0]);
Emails.Add(email);
}
}
}
return true;
}
catch (Exception)
{
return false;
}
}
As u can see in above code, I have an action exactly when the thread work finished. Actually, I want to inform about finishing thread work.
but the problem is here: most of the times, I got this exception when I want to fetch messages from inbox.
The Read method cannot be called when another read operation is pending
if I remove the threadpool that will work well.
Im using threadPool just for ignoring UI lock and also knowing there the thread finished.
Is there any better way that you can suggest I?
Thanks for any helping...
Is there any better way that you can suggest?
Here is how I would do it in a modern (not anymore, if you read it in 2020) approach in my WPF application:
private async void DoSomethingAsync()
{
try
{
DoanloadEmailsCommand.IsEnabled = false;
await Task.Run(() =>
{
// Do something here. For example, work with the database, download emails, etc.
Emails = DownloadEmails();
});
}
finally
{
DoanloadEmailsCommand.IsEnabled = true;
}
MessageBox.Show(string.Format("{0} emails have been downloaded.", Emails.Count));
}
The code inside the lambda expression passed to the Task.Run() method will be executed on another thread.
Straight after creating and running the task, control flow will be returned back to the caller (in our case to the UI message loop eventually, that will continue processing other events).
When the task finishes, some "wake-up" message is sent to the application's message queue, and when the message loop receives and handles this message, the execution will continue where it has been left off.
In our case, when the task finishes, the execution will be continued on the main thread from the next line following the "await Task.Run()" call ().
So the command object will be enabled (it would be bound to a button, let's say "Download Emails", so the button will become enabled also) and the message box saying how many emails will have been downloaded will be shown.
As you can see the code is pretty clean and easy to read and understand (once you know the basics of using the async/await keywords and the Task class).
(also read my comment above on your exception handling)

C#.Net - Threads are grabbing the same files within a loop

I'm trying to design a program that uses an external OCR application to flip an image until its right side up. All of the image locations are kept in files[].
The problem is, doing one file at a time is too slow to handle the tens of thousands of images I have. I need to launch several instances of the OCR program to scan multiples images at the same time.
My crappy implementation is the following:
public Program(string[] files)
{
for(int i = 0; i < files.Length; i++)
{
ThreadStart start = () => {flip(files[i]);};
Thread t = new Thread(start);
t.Start();
if(i % 5 == 0)
{
t.Join();
}
}
}
The code is supposed to launch 5 instances of the OCR program. On every fifth, it waits for the thread to close before continuing. This is supposed to act as a buffer.
However, what's happening instead is that repeating files are being passed into the OCR program instead of a different one for each iteration. Different threads are grabbing the same file. This causes a crash when the different instances of the OCR application go to work on the same file.
Does anyone have any idea whats going on, or know a completely different approach I can take?
You're suffering from a problem called accessing a modified closure. The value of i is changing as the threads are starting. Change the code to use a local variable instead.
for (int i = 0; i < args.Length; i++)
{
int currenti = i;
ThreadStart start = () => { flip(files[currenti]); };
Thread t = new Thread(start);
t.Start();
if (i % 5 == 0)
{
t.Join();
}
}
The problem is that your lambda expression is capturing the variable i, rather than its value for that iteration of the loop.
There are two options:
Capture a copy
for (int i = 0; i < files.Length; i++)
{
int copy = i;
ThreadStart start = () => flip(files[copy]); // Braces aren't needed
...
}
Use foreach - C# 5 only!
This won't help as much in your case because you're joining on every fifth item, so you need the index, but if you didn't have that bit and if you were using C# 5, you could just use:
foreach (var file in files)
{
ThreadStart start = () => flip(file);
...
}
Note that prior to C# 5, this would have had exactly the same problem.
For more details of the problem, see Eric Lippert's blog posts (part one; part two).

Creating a responsive version of a complex function [duplicate]

This question already has answers here:
Is there a code template/design pattern I can use when reacting to mouse clicks or button presses? [closed]
(4 answers)
Closed 9 years ago.
I am working on a little project. I need to implement some kind of an algorithm which in most cases will use much of a CPU's resources and therefore take some time to execute and return. I want this method to be kind of responsive and notify of any progress. I might also want to do some other processes while doing these computations.
Consider this class that has the complex method
class Engine
{
public int ComplexMethod(int arg)
{
int result = 0;
for (int i = 0; i < 100000; i++)
{
for (int j = 0; j < 10000; j++)
{
// some complex and time-consuming computations
}
// it would be nice to get notified on arriving this point for example
}
return result;
}
}
What is the best approach to this case?
EDIT: I should have mentioned that it is an app with UI (a WPF application).
You can run the process in a new thread using Task.Run, and use the IProgress<T> interface to notify progress:
class Engine
{
public int ComplexMethod(int arg, IProgress<double> progress)
{
int result = 0;
for (int i = 0; i < 100000; i++)
{
for (int j = 0; j < 10000; j++)
{
// some complex and time-consuming computations
}
progress.Report(i / 100000);
}
return result;
}
}
...
var progress = new Progress<double>(p => ShowProgress(p));
var result = await Task.Run(() => engine.ComplexMethod(arg, progress));
ShowResult(result);
If you have a UI (which is likely), the progression delegate will automatically be called on the UI thread, using Control.Invoke (Windows Forms) or Dispatcher.Invoke (WPF, WinRT, Silverlight), provided that the Progress<T> instance was created on the UI thread.
Note that async/await won't help (inside the method) if the computation is CPU-bound. However it can be used to make it easier to retrieve the result, as shown above. If for some reason you can't or don't want to use await, you can use ContinueWith, specifying TaskScheduler.FromCurrentSynchronizationContext for the scheduler parameter.
Assuming you are using .NET 4.5 (C# 5), you can use TPL (http://msdn.microsoft.com/en-us/library/dd997423(v=vs.110).aspx).
With not knowing your algorithm, all I can suggest is that you return a Task<int> instead of returning a int. This will allow for the function to be ran easily in parallel with other tasks.
I would recommend the following:
public Task<int> ComplexMethodAsync(int arg)
{
Task.Run(()=>ComplextMethod(arg));
}
Now, when you run this method, the ComplexMethod(arg) will be called on a separate thread from the ThreadPool. Call it with:
await ComplextMethodAsync(xyz);
Check out async/await for more information.

Categories

Resources