Parallel.Invoke for threads in c# - c#

Can anybody tell me how to invoke all threads at once from a list of threads.
actually I have saved all threads in a list after creating them but if I use th.start() and th.join() methods, every thread starts one by one. I want them to start all at once.
I've used time function to see the starting and ending time for each thread but non of them starts simultaneously.
I am starting thread like this:
foreach (Thread st in threadss)
{
st.Start();
st.Join();
}
but I want to start them like this:
Parallel.Invoke(() => st1.Start(), () => st2.Start(), .....);
please help

Why not .Start() them first, then .Join() them? Should work fine.
foreach (var st in threadss) {
st.Start();
}
foreach (var st in threadss) {
st.Join();
}

Related

Parallel For and background worker

I have this simple for:
for (int i = 0; i < nro_archivos; ++i) //Cargar el objeto img
{
string nombrearchivo = archivosdicom[i].FullName;
img.Add(new ImagenDicom(nombrearchivo));
Progress_Bar_Loading_Images.PerformStep();
}
followed by this:
decimal[] sliceseparation_imagen = new decimal[img.Count - 1];
for (int i = 0; i < img.Count; i++)
{
if (i < img.Count - 1)
{
sliceseparation_imagen[i] = Math.Abs(img[i + 1].Z - img[i].Z);
}
}
sliceseparation_promedio = sliceseparation_imagen.Average();
Now, my challenge is:
I implemented Paralell For but can't use the progressbar.. so I was thinking on using BackgroundWorker but the problem is that the operation right after the for is dependent on the load of the object img which happens in the for so until that's not done I can't continue.
My understanding of BackGroundWorker is that it executes in the background while the main program continues its execution, so this approach will bring errors when trying to access an img object that has not been created by the time the main program reaches the code outside the for.
Does it worth to use Background Worker in this case to speed up the load of the img object? if it does, how do I wait until the backgroundworker has done its job to then continue with the execution of the main program? I need to report progress on the for operation to the user so using a parallel for without something that would allow me to report back to the user won't work.
Thanks,
Matias.
If I understood the problem right here, you have one set of work when you're loading the image, you can care less about this one and pretend this can happen in parallel anyway but the problem is you need to report progress.
And after loading it you have one other block of work you need to do so, you can do it right away or you can do it after all the images are loaded.
Instead of parallel, you can go for Tasks. Access UI thread through a UI dispatcher so you don't have to worry about UI thread access issues.
var tasks = new List<Task>
{
Task.Run(() => {
// Block 1
// Use a proper dispatcher here to access the UI thread so you can report your progress}),
};
Task.WaitAll(tasks);
Now you have got your loads done, and you can progress with your second block of work.
But, as I can see you only need the average out of it and you don't need proper order to get average.
var tasks = new List<Task>
{
Task.Run(() => { /* for loop logic #1 */})
.ContinueWith((x)=> {
// Get your task result and execute second block
})
};
Task.WaitAll(tasks);
Now you have a continued task with it and all you have to do is call for an average after this is done.
You can go with two separate blocks too. I figured as these tasks are intertwined, why can't you just continue with one task anyway.
Using Tasks may help
var tasks = new List<Task>
{
Task.Run(() => { /* for loop logic #1 */
/* when interacting w/UI either use Dispatcher
for WPF for control.Invoke in winforms */
}),
Task.Run(() => { /* for loop logic #2 */})
};
Task.WaitAll(tasks.ToArray());

How to wait for a function execution for specific duration

My C# application stops responding for a long time, as I break the Debug it stops on a function.
foreach (var item in list)
{
xmldiff.Compare(item, secondary, output);
...
}
I guess the running time of this function is long or it hangs. Anyway, I want to wait for a certain time (e.g. 5 seconds) for the execution of this function, and if it exceeds this time, I skip it and go to the next item in the loop. How can I do it? I found some similar question but they are mostly for processes or asynchronous methods.
You can do it the brutal way: spin up a thread to do the work, join it with timeout, then abort it, if the join didn't work.
Example:
var worker = new Thread( () => { xmlDiff.Compare(item, secondary, output); } );
worker.Start();
if (!worker.Join( TimeSpan.FromSeconds( 1 ) ))
worker.Abort();
But be warned - aborting threads is not considered nice and can make your app unstable. If at all possible try to modify Compare to accept a CancellationToken to cancel the comparison.
I would avoid directly using threads and use Microsoft's Reactive Extensions (NuGet "Rx-Main") to abstract away the management of the threads.
I don't know the exact signature of xmldiff.Compare(item, secondary, output) but if I assume it produces an integer then I could do this with Rx:
var query =
from item in list.ToObservable()
from result in
Observable
.Start(() => xmldiff.Compare(item, secondary, output))
.Timeout(TimeSpan.FromSeconds(5.0), Observable.Return(-1))
select new { item, result };
var subscription =
query
.Subscribe(x =>
{
/* do something with `x.item` and/or `x.result` */
});
This automatically iterates through each item and starts a background computation of xmldiff.Compare, but only allows each computation to take as much as 5.0 seconds before returning a default value of -1.
The subscription variable is an IDisposable, so if you want to abort the entire query before it completes just call .Dispose().
I skip it and go to the next item in the loop
By "skip it", do you mean "leave it there" or "cancel it"? The two scenarios are quite different. But for both two I suggest you use Task.
//generate 10 example tasks
var tasks = Enumerable
.Range(0, 10)
.Select(n => new Task(() => DoSomething(n)))
.ToList();
var maxExecutionTime = TimeSpan.FromSeconds(5);
foreach (var task in tasks)
{
if (task.Wait(maxExecutionTime))
{
//the task is finished in time
}
else
{
// the task is over time
// just leave it there
// the loop continues
// if you want to cancel it, see
// http://stackoverflow.com/questions/4783865/how-do-i-abort-cancel-tpl-tasks
}
}
One thing to improve is "do you really need to run your tasks one by one?" If they are independent you can run them in parallel.

Instantiating a Thread within a foreach loop in C#

I have a function that connects to a Multiple SQL server instances to fetch a set of data from each server for comparison of the data among multiple environments
I have a collection of the connection strings
I am calling this method in a foreach loop for each connection string in the collection
Since the data is fetched from different servers individually one at a time it takes up a lot of time
I would like to know if i use threads to call this method every time what would be the best way to do it?
There are a couple of ways to do this
1.) create a set of tasks and then do "await Task.WaitAll(listOfTasks)"
2.) Use Parallel.ForEach
3.) Manage threads
Managing threads
I do this in 2 steps:
1.) Create a list of threads
List<Thread> threads = new List<Thread>();
foreach(var connectionString in ConnectionStrings)
{
var thread = new Thread(DoWork);
thread.Start(connectionString);
threads.Add(thread);
}
2.) Join the threads to the current thread, has the effect of blocking until all are complete.
foreach(var thread in threads)
{
thread.Join()
}
You could Join the threads and make the program wait all of them until they are finished. It is a good pratice before moving to the next step. Look the code bellow with the comment, for sample:
// list of threads
List<Thread> threads = new List<Thread>();
// list of the results for each thread
List<SomeTypeDto> results = new List<SomeTypeDto>();
foreach(var connectionString in connectionStringList) {
// create the thread
Thread thread = new Thread(() => {
// access the database
SomeTypeDto result = /* process some result data*/;
lock (results) {
results.Add(result);
}
});
threads.Add(thread);
}
// start all threads
foreach (Thread thread in threads) {
thread.Start();
}
// Wait for all the threads to finish
foreach (Thread thread in threads) {
thread.Join();
}

Execute a list of threads

I have a list of a object "Code":
List<Code> listCodes = new List<Code>();
I need to execute each code inside the list in a Thread, but I have not idea how to do that, because I tried to do something like:
foreach(Code c in listCodes)
{
Thread tr = new Thread(delegate() {
Execute(c.CodeLine);
});
}
This foreach is in a timer, because those Codes will be executed all the time, but when I do that the same code is executed a lot of times even if the first execution wasn't finished, if the code takes like 5 seconds to be executed and finished and the timer is 500ms it will be executed 10 times if I disable the timer after 5 seconds for exemple.
I couldn't think anything to execute the codes in the list, each one in their thread, but I want to execute the thread of the code 0(for exemple) only if it was finished after the execution.
Thank you.
System.Threading.Monitor.TryEnter is perfect for the job:
foreach(Code c in listCodes) {
Code a = c;
new Thread(delegate() {
if(Monitor.TryEnter(a)) {
Execute(a.CodeLine);
Monitor.Exit(a);
}
}) { IsBackground = true }.Start();
}
What it does is try to acquire an exclusive lock on the Code object. If it can't (i.e. the Code is already executing) then nothing will happen; otherwise, the lock is acquired, and released when execution is complete.
I think using Threads like this is inefficient, you should use Tasks instead.
In C# 5, I would do it like this:
private static async Task RunCode(Code code, TimeSpan delay)
{
while (!Stopped)
{
var delayTask = Task.Delay(delay);
Execute(code.CodeLine);
await delayTask;
}
}
And then start it once (i.e. not in a timer):
foreach (Code c in listCodes)
{
Task.Run(() => RunCode(c, TimeSpan.FromMilliseconds(1000)));
}
You need to actually wait for the Threads to finish. You do this by calling Join:
List<Thread> threads = new List<Threads>();
foreach(Code c in listCodes)
{
Thread tr = new Thread(delegate() {
Execute(c.CodeLine);
});
threads.Add(tr);
}
foreach(Thread tr in threads)
{
tr.Join();
}
This is all inside your outer timer.

Launching multiple threads, Why must you wait?

I have been playing around with Threads and Tasks (.net 4) and noticed some odd behavior when you launch multiple threads without waiting a few miliseconds between each thread started call.
The example below when run does not output what I expected:
1
2
1
2
But instead only outputs:
2
2
2
2
Below is the code that I am running.
public static void Main()
{
var items = new[] {"1", "2"};
foreach (var item in items)
{
var thread = new Thread(() => Print(item));
thread.Start();
//var task = Task.Factory.StartNew(() => Print(item));
}
}
static void Print(string something)
{
while (true)
{
Console.WriteLine(something);
Thread.Sleep(1000);
}
}
Now when I call Thread.Sleep(50) after the thread.Start() then only does the output look as expected
1
2
1
2
My question is:
Why when you do not wait between launching both threads does the first
thread loose the method's parameter value you initially started it with?
i.e. first thread is launched with parameter of "1", second thread is launched with parameter of "2", however first thread's parameter becomes "2" as well? This makes no sense, especially since Print() method paramter is a value type of string.
Google "access to modified closure". What's happening is your local variable "item" is getting it's value changed before the Print function is invoked. A solution would be to create a new variable inside the scope of the loop and assign item to it.
The item is evaluated at the time that the thread you create starts due to c# closures. Another way to force the item to evaluate is to introduce a variable so that the closure will include it like so:
foreach (var item in items)
{
var closedItem = item;
var thread = new Thread(() => Print(closedItem));
thread.Start();
}
Your problem is not with threads. Your problem is with the closure and the foreach. You can read here why:
http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx
When you play with the timing of the threads you reorder the timings of the main thread as well so sometimes the loop will be executed before the print method of the new thread runs and sometimes after.
Show us the thread starting code and you'll find that you do not pass a constant string but a reference variable and in between calling those Start methods you are probably changing the variable.

Categories