How to start loop fresh for every call of function - c#

I am trying to stop the loop when called the function.suppose first i call the function one loop is running and again called that function i need to break the first called loop and start the loop fresh again.
public void HitTimer(int leagueid,int dposition,int teamid,int round)
{
//if (_hubContext == null)
//{
// _hubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
// }
int m = 1;
for (int k = 1; k < 91; k++)
{
System.Threading.Thread.Sleep(1000);
if (k == 90)
{
AutoAddDraftPlayer(leagueid, dposition,teamid,round);
}
else if (_hubContext != null)
{
_hubContext.Clients.All.broadcastTime(90 - k, leagueid, teamid, round);
//hubContext.Clients.Client(Context.ConnectionId).broadcastTime(90 - k);
//Clients.Caller.broadcastTime(90 - k);
}
m++;
}
}
my code is above and let me know how to solve

You could refactor this to be Task based and then use a cancellation token to cancel the first task if the method is called again. The details of how to do all of this is here: https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation
static tokenSource = new CancellationTokenSource();
static CancellationToken ct = tokenSource.Token;
static Task task = null;
public void HitTimer(int leagueid,int dposition,int teamid,int round)
{
if (task != null)
tokenSource.Cancel();
try
{
if (task != null)
task.Wait();
}
catch (AggregateException e)
{
foreach (var v in e.InnerExceptions)
Console.WriteLine(e.Message + " " + v.Message);
}
task = Task.Factory.StartNew(() => DoLoop(leagueid, dposition, teamid, round), tokenSource.Token)
}
public void DoLoop(int leagueid,int dposition,int teamid,int round)
{
int m = 1;
for (int k = 1; k < 91; k++)
{
if (ct.IsCancellationRequested)
{
break;
}
System.Threading.Thread.Sleep(1000);
if (k == 90)
{
AutoAddDraftPlayer(leagueid, dposition,teamid,round);
}
else if (_hubContext != null)
{
_hubContext.Clients.All.broadcastTime(90 - k, leagueid, teamid, round);
//hubContext.Clients.Client(Context.ConnectionId).broadcastTime(90 - k);
//Clients.Caller.broadcastTime(90 - k);
}
m++;
}
}

Related

Find inconsistent and consecutive objects from List in C#

I'm having trouble with getting a consecutive and nonconsecutive number from list. I'm sure it's pretty simple, but i can't get it.
If consecutiveNum=2, then if result from before last and last is equal, i need to throw an exception.
If nonConsecutiveNum=4, then if from 10 pieces there are 4 with same result, i need to throw an exception.
I'm trying with nested loops and couple checks, but i didn't succeeded at all. Same is for both cases, i tried a couple solutions with System.LINQ, but again i don't get the result i need.
Thanks in advance to all of you!
int consecutiveNum = 2;
int nonConsecutiveNum = 4;
int counter = 1;
var sensInfo = new ResultInfo()
{
Product = CurrentLot.Info.Product,
Result = code
};
if (consecutiveNum > 0)
{
for (int i = ListSensors.Count + 1; i >= 0; i--)
{
if (sensInfo.Result == ListSensors[i].Result)
{
counter++;
if (counter >= consecutiveNum)
{
throw new Exception("Consecutive num");
}
}
}
}
if (nonConsecutiveNum > 0)
{
for (int i = 0; i < ListSensors.Count; i++)
{
for (int j = i + 2; j < ListSensors.Count - 2; j++)
{
if (ListSensors[i].Result == ListSensors[i+1].Result)
continue;
if (ListSensors[i].Result == ListSensors[j].Result)
{
counter++;
if (counter >= nonConsecutiveNum)
{
throw new Exception("NonConsecutive num");
}
}
}
}
}
// consecutiveNum
for (int i = ListSensors.Count - 1; i >= 0; i--)
{
if (sensInfo.Result == ListSensors[i].Result)
{
counter++;
if (counter >= consecutiveNum)
{
throw new Exception("Consecutive num");
}
}
else
{
counter = 1;
}
}
// nonConsecutiveNum
IDictionary<int, int> resultCountDictionary = new Dictionary<int,int>();
foreach (var listSensor in ListSensors)
{
if (resultCountDictionary.ContainsKey(listSensor.Result))
{
resultCountDictionary[listSensor.Result] = resultCountDictionary[listSensor.Result] + 1;
if (resultCountDictionary[listSensor.Result] >= nonConsecutiveNum)
{
throw new Exception();
}
}
else
{
resultCountDictionary.Add(listSensor.Result, 1);
}
}
Consecutive:
Using MoreLinq's Window function:
ListSensors.Window(consecutiveNum).Any(x => x.Distinct().Count() == 1);
Nonconsecutive:
ListSensors.Any(x => ListSensors.Count(s => s == x) >= nonConsecutiveNum);

Multiple iterations with multithreading

I rewrote method, which initially was for only one thread, to work with many threads. Now, this method accepts two concurrent collections: ConcurrentBag, which was List, and ConcurrentQueue, which was Queue.
The purpose is to match two titles from both collection and make some logic, which is simple value assignment in ConcurrentBag items. I know, for sure, that all symbols in ConcurrentBag are in ConcurrentQueue.
When I wrote this for multi threads, it occured that some of titles do not match (~20%), which did not happen when there was on thread. Only during debugging I can match these titles and then values are assigned. There has to be some problem with iterating these two collections. Maybe in the same time many threads reads values from the same item, but only reading should not be problem?
Below code:
public void UpdateWithPercent(ref ConcurrentBag<Book> refList, ConcurrentQueue<Book> list)
{
var size = list.Count;
int numProcs = Environment.ProcessorCount;
var divider = CalculatBiggestDivider(size);
var nextIteration = 0;
var remainingWork = numProcs;
var internalRefList = refList;
using (ManualResetEvent mre = new ManualResetEvent(false))
{
for (int i = 0; i < numProcs; i++)
{
ThreadPool.QueueUserWorkItem(delegate
{
IEnumerable<Book> partialList;
while (-(nextIteration - Interlocked.Add(ref nextIteration, (partialList = DequeueChunk(list, divider)).Count()))> 0)
{
foreach (var item in partialList)
{
foreach (var x in internalRefList)
{
if (x.Title == item.Title)
{
x.Orders += item.Orders;
break;
}
};
}
}
if (Interlocked.Decrement(ref remainingWork) == 0)
{
mre.Set();
}
});
}
mre.WaitOne();
}
refList = internalRefList;
}
private int CalculatBiggestDivider(int count)
{
var divider = 1;
for (int i = 30; i > 0; i--)
{
if (count % i == 0)
{
divider = i;
break;
}
}
return divider;
}
private IEnumerable<T> DequeueChunk<T>(ConcurrentQueue<T> queue, int chunkSize)
{
for (int i = 0; i < chunkSize && queue.Count > 0; i++)
{
T item;
bool success = queue.TryDequeue(out item);
if (!success)
{
i = chunkSize;
continue;
}
yield return item;
}
}
Eventually I decided to resign from nestedloops and used ConcurrentDictionary. Now it works.
public void UpdateWithPercent(ref ConcurrentDictionary<string, Book> refList, List<Book> list, int ticker, int maxTimes)
{
var size = list.Count;
int numProcs = Environment.ProcessorCount;
var divider = CalculatBiggestDivider(size);
var nextIteration = 0;
var remainingWork = numProcs;
var internalRefList = refList;
using (ManualResetEvent mre = new ManualResetEvent(false))
{
for (int i = 0; i < numProcs; i++)
{
ThreadPool.QueueUserWorkItem(delegate
{
int index = 0;
while ((index = Interlocked.Add(ref nextIteration, divider) - divider) < size)
{
foreach (var item in list.GetRange(index, divider))
{
Book x;
if (internalRefList.TryGetValue(item.Title, out x))
{
x.Orders += item.Orders;
}
};
}
if (Interlocked.Decrement(ref remainingWork) == 0)
{
mre.Set();
}
});
}
mre.WaitOne();
}
refList = internalRefList;
}

Parallel recursion in C#

class CustomData
{
public int TNum;
public int TResult;
}
public static int F_recursion(int n, int w)
{
if (n == 0 || w == 0)
return 0;
else if (s[n] > w)
return F_recursion(n - 1, w);
else
{
return Math.Max(F_recursion(n - 1, w),
p[n] + F_recursion(n - 1, w - s[n]));
}
}
public static int F_recursion2(int n, int w)
{
int numba = 0;
int countCPU = 8;
Task[] tasks = new Task[countCPU];
for (var j = 0; j < countCPU; j++)
tasks[j] = Task.Factory.StartNew(
(object p) =>
{
var data = p as CustomData; if (data == null) return;
data.TResult = F_recursion(n - data.TNum, w);
},
new CustomData() { TNum = j });
Task.WaitAll(tasks);
numba = (tasks[0].AsyncState as CustomData).TResult
+ (tasks[1].AsyncState as CustomData).TResult
+ (tasks[2].AsyncState as CustomData).TResult
+ (tasks[3].AsyncState as CustomData).TResult;
return numba;
}
How could i make F_recursion2 method to work in parallel? With my code current results are
Time in milliseconds for recursion: 1,075
recursion( 150 ) = 7,237
Time in milliseconds for parallel recursion: 1,581
recursion( 150 ) = 28,916
As you can see parallel approach prints 4 times bigger number and it takes more time to compute which doesn't make sense. How could I approach this problem that recursion would work in parallel?
EDIT Changed for loop to Parallel.For still same results as above.
public static int F_recursion2(int n, int w)
{
int numba = 0;
int countCPU = 8;
Task[] tasks = new Task[countCPU];
Parallel.For(0, countCPU, j =>
{
tasks[j] = Task.Factory.StartNew(
(object p) =>
{
var data = p as CustomData; if (data == null) return;
data.TResult = F_recursion(n - data.TNum, w);
},
new CustomData() { TNum = j });
});
Task.WaitAll(tasks);
numba = (tasks[0].AsyncState as CustomData).TResult
+ (tasks[1].AsyncState as CustomData).TResult
+ (tasks[2].AsyncState as CustomData).TResult
+ (tasks[3].AsyncState as CustomData).TResult;
return numba;
}
On solution which comes to my mind is using Parallel.For. To do this, you should just implement the for using Parallel.For. To see an example, visit here.

ParallelFor not cancelling all threads immediately if condition met

Code always waits until currently running tasks have finished before the OperationCancelledException is thrown.
I would like the program to stop immediately on the condition being true.
static void Main()
{
// want to break out of a Parallel.For immediately when a condition occurs
var cts = new CancellationTokenSource();
var po = new ParallelOptions();
po.CancellationToken = cts.Token;
long counterTotal = 0;
try
{
// want to have a sum of counts at the end
Parallel.For<long>(1, 26, po, () => 0, delegate(int i, ParallelLoopState state, long counterSubtotal)
{
po.CancellationToken.ThrowIfCancellationRequested();
Console.WriteLine(i.ToString());
for (int k = 0; k < 1000000000; k++)
{
counterSubtotal++;
if (i == 4 && k == 900000000)
{
cts.Cancel();
// Would like to break out here immediately
}
}
return counterSubtotal;
}, (x) => Interlocked.Add(ref counterTotal, x)
);
}
catch (OperationCanceledException e)
{
Console.WriteLine("Cancelled");
Console.WriteLine("Total iterations across all threads {0}", String.Format("{0:n0}", counterTotal));
Console.ReadLine();
}
}
I found putting a breakpoint on cts.Cancel() and in the catch demonstrates what is happening.
Have looked at state.Stop too.
This is a simplified version of other code.
Perhaps Parallel.For isn't ideal for things which are very long running inside the method if we want to break out immediately.
Update2:
The code now works as expected and gives a good total
static void Main()
{
// want to break out of a Parallel.For immediately when a condition occurs
var cts = new CancellationTokenSource();
var po = new ParallelOptions();
po.CancellationToken = cts.Token;
long counterTotal = 0;
try
{
// want to have a sum of counts at the end
// using type param here to make counterSubtotal a long
Parallel.For<long>(1, 26, po, () => 0, delegate(int i, ParallelLoopState state, long counterSubtotal)
{
Console.WriteLine(i.ToString());
// 1 billion
for (int k = 0; k < 1000000000; k++)
{
//po.CancellationToken.ThrowIfCancellationRequested();
if (po.CancellationToken.IsCancellationRequested)
{
return counterSubtotal;
}
counterSubtotal++;
if (i == 4 && k == 400000000)
{
Console.WriteLine("Inner Cancelled");
cts.Cancel();
}
}
return counterSubtotal;
}, (x) => Interlocked.Add(ref counterTotal, x)
);
}
catch (OperationCanceledException e)
{
Console.WriteLine("Cancelled");
Console.WriteLine("Total iterations across all threads {0}", String.Format("{0:n0}", counterTotal));
Console.ReadLine();
}
}
If you want it to break more "immediately" than you need to check the cancellation token inside of your inner for. As it is now, it will check for cancel before entering, but after that it won't look at the token again.
for (int k = 0; k < 1000000000; k++)
{
po.CancellationToken.ThrowIfCancellationRequested();
counterSubtotal++;
if (i == 4 && k == 900000000)
{
cts.Cancel();
}
}

Wait until all threads finished their work in ThreadPool

i have this code:
var list = new List<int>();
for(int i=0;i<10;i++) list.Add(i);
for(int i=0;i<10;i++)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(x => {
Console.WriteLine(x);
}), list[i]);
}
And i want to know when all threadpools threads finished their work. How i can to do that?
You'll need to track this yourself.
One option for this is to use a counter and a reset event:
int toProcess = 10;
using(ManualResetEvent resetEvent = new ManualResetEvent(false))
{
var list = new List<int>();
for(int i=0;i<10;i++) list.Add(i);
for(int i=0;i<10;i++)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(x => {
Console.WriteLine(x);
// Safely decrement the counter
if (Interlocked.Decrement(ref toProcess)==0)
resetEvent.Set();
}),list[i]);
}
resetEvent.WaitOne();
}
// When the code reaches here, the 10 threads will be done
Console.WriteLine("Done");
In .NET Framework 4+ use the handy System.Threading.CountdownEvent class:
const int threadCount = 10;
var list = new List<int>(threadCount);
for (var i = 0; i < threadCount; i++) list.Add(i);
using (var countdownEvent = new CountdownEvent(threadCount))
{
for (var i = 0; i < threadCount; i++)
ThreadPool.QueueUserWorkItem(
x =>
{
Console.WriteLine(x);
countdownEvent.Signal();
}, list[i]);
countdownEvent.Wait();
}
Console.WriteLine("done");
I am not sure if ThreadPool exposes such functionality but you can use wait handles and by the way iterating twice seems unnecessary:
var events = new ManualResetEvent[10];
var list = new List<int>();
for (int i = 0; i < 10; i++)
{
list.Add(i);
events[i] = new ManualResetEvent(false);
int j = i;
ThreadPool.QueueUserWorkItem(x => {
Console.WriteLine(x);
events[j].Set();
}, list[i]);
}
WaitHandle.WaitAll(events);
This is how I would do it.
class Program
{
static void Main(string[] args)
{
var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
using (var countdown = new Countdown(items.Length))
{
foreach (var item in items)
{
ThreadPool.QueueUserWorkItem(o =>
{
Thread.SpinWait(100000000);
Console.WriteLine("Thread Done!");
countdown.Signal();
});
}
countdown.Wait();
}
Console.WriteLine("Job Done!");
Console.ReadKey();
}
public class Countdown : IDisposable
{
private readonly ManualResetEvent done;
private readonly int total;
private volatile int current;
public Countdown(int total)
{
this.total = total;
current = total;
done = new ManualResetEvent(false);
}
public void Signal()
{
lock (done)
{
if (current > 0 && --current == 0)
done.Set();
}
}
public void Wait()
{
done.WaitOne();
}
public void Dispose()
{
done.Dispose();
}
}
}
The thread pool does not tell you when the thread has finished executing, so the work item must do it itself. I changed the code like this:
var list = new List<int>();
ManualResetEvent[] handles = new ManualResetEvent[10];
for (int i = 0; i < 10; i++) {
list.Add(i);
handles[i] = new ManualResetEvent(false);
}
for (int i = 0; i < 10; i++) {
ThreadPool.QueueUserWorkItem(
new WaitCallback(x =>
{
Console.WriteLine(x);
handles[(int) x].Set();
}), list[i]);
}
WaitHandle.WaitAll(handles);
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(xyz));
}
bool working = true;
ThreadPool.GetMaxThreads(out int maxWorkerThreads, out int maxCompletionPortThreads);
while (working)
{
ThreadPool.GetAvailableThreads(out int workerThreads, out int completionPortThreads);
//Console.WriteLine($"{workerThreads} , {maxWorkerThreads}");
if (workerThreads == maxWorkerThreads)
{ working = false; }
}
//when all threads are completed then 'working' will be false
}
void xyz(object o)
{
console.writeline("");
}

Categories