I'm creating an UWP application that needs to measure the time the user is looking at an object. This application has around 300 objects to measure the time of. To do this we will be using around 300 timers. To achieve this we will have to create 300 stopwatches individually which is highly inefficient.
The timer starts when the user is looking at the corresponding object and stops when the user is no longer looking at the corresponding object. If the user's gaze is fixated on the corresponding object again the timer of course starts again. At the end all of the times of the stopwatches will be saved into a file. Creating 300 stopwatches requires a new line of code for every stopwatch which does not seem very efficient. I have tried to automate the stopwatch creation process by using Enumerable.range but so far i have not been able to find a solution.
/// <summary>
/// All stopwatches for every word. In our real code we will have around 300 stopwatches.
/// </summary>
Stopwatch Stopwatch1 = new Stopwatch();
Stopwatch Stopwatch2 = new Stopwatch();
Stopwatch Stopwatch3 = new Stopwatch();
Stopwatch Stopwatch4 = new Stopwatch();
Stopwatch Stopwatch5 = new Stopwatch();
Stopwatch Stopwatch6 = new Stopwatch();
Stopwatch Stopwatch7 = new Stopwatch();
Stopwatch Stopwatch8 = new Stopwatch();
Stopwatch Stopwatch9 = new Stopwatch();
Stopwatch Stopwatch10 = new Stopwatch();
So, at first you need to get a list of the available objects. You can use the following code to create a generic dictionary that keeps a stopwatch for every object you have. There is also a sample implementation of a method that generates a gazing survey.
You still have to add the code that calls the start and stop methods.
class Program
{
static Dictionary<object, Stopwatch> stopwatchesByObject;
static void Main(string[] args)
{
List<object> objects = new List<object>();
// now you have to fill the objects list...
stopwatchesByObject = new Dictionary<object, Stopwatch>();
foreach (var o in objects)
{
stopwatchesByObject.Add(o, new Stopwatch());
}
}
// Call this method when the user starts gazing at object o
static void StartGazingAt(object o)
{
stopwatchesByObject[o].Start();
}
// Call this method when the user stops gazing at object o
static void StopGazingAt(object o)
{
stopwatchesByObject[o].Stop();
}
static void CreateStatistics()
{
StringBuilder sb = new StringBuilder();
foreach (var entry in stopwatchesByObject)
{
sb.AppendLine($"Gazed at {entry.Key.ToString()} for {entry.Value.Elapsed.TotalSeconds} seconds.");
}
File.WriteAllText("c:\\temp\\statictics.txt", sb.ToString());
}
}
I liked Stefan Illners approach and wanted to add some linq-magic, which, imo, is really neat and good readable.
using System.Linq;
var myListOfItemsToWatch = new List<object> { "foo", "bar", "baz" };
var listOfStopwatches = myListOfItemsToWatch.ToDictionary(watchItem =>
watchItem, i => new Stopwatch()
);
Just only define List<Stopwatch>()
var l = new List<Stopwatch>();
for (var i = 0; i < 300; i++)
{
var w = Stopwatch.StartNew();
w.Stop();
l.Add(w);
}
To show you how to deal with it see this example
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
public static List<Stopwatch> sws = new List<Stopwatch>();
public static List<Thread> threads = new List<Thread>();
static void Main()
{
for (var i = 0; i < 300; i++)
{
threads.Add(new Thread(Dummy));
sws.Add(new Stopwatch());
}
for(int i = 0; i < 300; i++) sws[i].Start();
new Thread( () => { for(int i = 0; i < 5; i++) threads[i].Start(i); }).Start();
new Thread( () => { for(int i = 5; i < 10; i++) threads[i].Start(i); }).Start();
new Thread( () => { for(int i = 10; i < 15; i++) threads[i].Start(i); }).Start();
new Thread( () => { for(int i = 15; i < 20; i++) threads[i].Start(i); }).Start();
new Thread( () => { for(int i = 20; i < 25; i++) threads[i].Start(i); }).Start();
new Thread( () => { for(int i = 25; i < 30; i++) threads[i].Start(i); }).Start();
new Thread( () => { for(int i = 30; i < 35; i++) threads[i].Start(i); }).Start();
new Thread( () => { for(int i = 35; i < 40; i++) threads[i].Start(i); }).Start();
Console.Read();
}
static void Dummy(object data)
{
int i = (int)data;
Thread.Sleep(250);
sws[i].Stop();
Console.WriteLine(sws[i].ElapsedMilliseconds.ToString());
}
}
}
Related
I need to reduce number of tasks created/executed in small piece of code because there is potentially big memory allocation.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TaskMemoryUsage
{
class Program
{
static void Main(string[] args)
{
int availableTaskCount = Environment.ProcessorCount;
OriginalCalculationMethod();
FirstCalculationMethod(availableTaskCount);
SecondCalculationMethod(availableTaskCount);
Console.ReadKey();
}
static TaskResult Calculate(int i)
{
//a lot of complicated calculations are made here
return new TaskResult();
}
static List<TaskResult> OriginalCalculationMethod()
{
List<Task<TaskResult>> workersArray = new List<Task<TaskResult>>();
long memStart = GC.GetTotalMemory(true);
for (int i = 0; i < 10000; ++i)
{
workersArray.Add(
Task.Factory.StartNew(
new Func<TaskResult>(() => Calculate(i))
));
}
Task.WaitAll(workersArray.ToArray());
long memEnd = GC.GetTotalMemory(true);
Console.WriteLine($"DIFFERENCE = {memEnd - memStart}");
return workersArray.Select(s => s.Result).ToList();
}
static List<TaskResult> FirstCalculationMethod(int availableTaskCount)
{
long memStart = GC.GetTotalMemory(true);
using (SemaphoreSlim semaphore = new SemaphoreSlim(availableTaskCount))
{
List<Task<TaskResult>> tasks = new List<Task<TaskResult>>();
for (int i = 0; i < 10000; ++i)
{
Task<TaskResult> task = Task.Factory.StartNew(() =>
{
try
{
semaphore.Wait();
return Calculate(i);
}
finally
{
semaphore.Release();
}
});
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
long memEnd = GC.GetTotalMemory(true);
Console.WriteLine($"DIFFERENCE = {memEnd - memStart}");
return tasks.Select(s => s.Result).ToList();
}
}
static List<TaskResult> SecondCalculationMethod(int availableTaskCount)
{
List<Task<TaskResult>> workersArray = new List<Task<TaskResult>>();
List<TaskResult> tasksResults = new List<TaskResult>();
long memStart = GC.GetTotalMemory(true);
for (int i = 0; i < 10000; ++i)
{
workersArray.Add(Task.Factory.StartNew(new Func<TaskResult>(() => Calculate(i))
));
if (workersArray.Count >= availableTaskCount)
{
Task.WaitAll(workersArray.ToArray());
tasksResults.AddRange(workersArray.Select(t => t.Result));
workersArray.Clear();
}
}
Task.WaitAll(workersArray.ToArray());
long memEnd = GC.GetTotalMemory(true);
Console.WriteLine($"DIFFERENCE = {memEnd - memStart}");
return tasksResults;
}
}
class TaskResult
{
public double[] calculationResult;
}
}
I gained best results for last solution, but I am not sure if i meassure it properly, so I want to ask if I properly measure memory allocation for this issue and if my solutions are correct or if there are better solutions for reduce memory allocation that is consumed at once.
I am exploring with the concept of starting a thread within another thread. this is the code I have come up with, this is watered down version of another program which I am developing currently however I found out that the second level of threads do not complete successfully.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication4
{
public class SomeClassA
{
public SomeClassA(string display)
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine(display);
}
}
public class MainSomeClassA
{
public List<SomeClassA> SomeClassaAList;
public List<Thread> ThreadList;
public MainSomeClassA()
{
ThreadList = new List<Thread>();
SomeClassaAList = new List<SomeClassA>();
for (int i = 0; i < 10; i++)
{
ThreadList.Add(new Thread(() => StartThread("Hello")));
}
WaitComplete();
}
public void WaitComplete()
{
bool AllThreadsAlive = true;
while (AllThreadsAlive)
{
AllThreadsAlive = false;
foreach (Thread t in ThreadList)
{
if (t.IsAlive)
{
AllThreadsAlive = true;
}
}
}
}
public void StartThread(string display)
{
SomeClassaAList.Add(new SomeClassA(display));
}
}
class Program
{
public static List<MainSomeClassA> MainSomeClassAList = new List<MainSomeClassA>();
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
MainSomeClassAList = new List<MainSomeClassA>();
List<Thread> ThreadList = new List<Thread>();
bool threadsAlive = true;
sw.Reset();
sw.Start();
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(AddToMainClassAList);
t.Start();
ThreadList.Add(t);
}
while (threadsAlive)
{
threadsAlive = false;
foreach (Thread t in ThreadList)
{
if (t.IsAlive)
{
threadsAlive = true;
}
}
}
sw.Stop();
Console.WriteLine("Elapsed Time: {0}", sw.ElapsedMilliseconds);
Console.ReadKey();
}
public static void AddToMainClassAList()
{
MainSomeClassAList.Add(new MainSomeClassA());
}
}
}
The above code does not print out "hello" and exits without creating the SomeClassA List.
The problem with your code is that you never start the inner threads. Change you constructor to look like this, and it will work:
public MainSomeClassA()
{
ThreadList = new List<Thread>();
SomeClassaAList = new List<SomeClassA>();
for (int i = 0; i < 10; i++)
{
ThreadList.Add(new Thread(() => StartThread("Hello")));
// Start thread here:
ThreadList[ThreadList.Count - 1].Start();
}
WaitComplete();
}
That said, I should point out that you're lucky the program doesn't crash. You have ten threads concurrently trying to modify the MainSomeClassAList object, some of which will necessarily force a reallocation of the internal buffer. As it is, if you print out the Count of the list at the end, you will find it isn't always 10 as it ought to be.
For the code to be truly correct, you would need to add synchronization around the call to Add() in the AddToMainClassAList() method. Same thing applies to the StartThread() method and the SomeClassaAList object.
Finally, your method for waiting on the threads is very poor. You should try to avoid polling at all costs. In this case, the Thread.Join() method is a reasonable choice (you should try to avoid blocking a thread at all, but for this example, it's unavoidable). For example, your busy loop can be replaced by this:
foreach (Thread thread in ThreadList)
{
thread.Join();
}
I was experimenting with tasks. Why does this output 10 and not each value of the loop?
public static void StartTasks()
{
Task[] tasks = new Task[10];
for (int i = 0; i < 10; i++)
tasks[i] = new Task(() => Console.WriteLine(i));
foreach (Task task in tasks)
{
task.Start();
}
}
C# lambdas capture a reference to the variable, not the value of the variable.
If you want to capture the value, you need to make a copy of it first inside the loop which causes the capture to get the reference to the locally scoped unchanging variable.
public static void StartTasks()
{
Task[] tasks = new Task[10];
for (int i = 0; i < 10; i++) {
int j = i;
tasks[i] = new Task(() => Console.WriteLine(j));
}
foreach (Task task in tasks)
{
task.Start();
}
}
In addition to the accepted answer, you can also pass a parameter to the task. For example,
using System;
using System.Threading.Tasks;
static void StartTasks(int instances)
{
var tasks = new Task[instances];
for (int i = 0; i < instances; i++)
{
tasks[i] = new Task((object param) =>
{
var t = (int)param;
Console.Write("({0})", t);
}, i);
}
Parallel.ForEach<Task>(tasks, (t) => { t.Start(); });
Task.WaitAll(tasks);
}
I'm trying to get the CPU% for all processes in parallel using C#'s TPL. The code that I have is:
private IDictionary<Process, int> _usage = new Dictionary<Process, int>();
public ProcessCpuUsageGetter()
{
Process[] processes = Process.GetProcesses();
int processCount = processes.Count();
Task[] tasks = new Task[processCount];
int counter = 0;
for (int i = 0; i < processCount; i++)
{
tasks[i] = Task.Factory.StartNew(() => DoWork(processes[i]));
}
Task.WaitAll(tasks);
}
private void DoWork(object o)
{
Process process = (Process)o;
PerformanceCounter pc = new PerformanceCounter("Process", "% Processor Time", process.ProcessName, true);
pc.NextValue();
Thread.Sleep(1000);
int cpuPercent = (int)pc.NextValue() / Environment.ProcessorCount;
_usage.Add(process, cpuPercent);
}
But it fails with An item with the same key has already been added. Any ideas on what I'm doing wrong?
The problem is the closure of the local variable i when passed to the expression for starting the task. This causes current value of i used by the DoWork(processes[i]) even when i being modified by the for.
Create a local variable:
for (int i = 0; i < processCount; i++)
{
int localI = i;
tasks[i] = Task.Factory.StartNew(() => DoWork(processes[localI]));
}
In below sample code, I use lambda function to make 3 threads doing different things. My goal is make the thread count configurable, so I was thinking using a loop to start threads. But I always got in static function can't call non-static members error. Can the community help me or direct me to a tutorial? Thanks a lot!
My Code:
internal class FeedClient
{
private static void Main(string[] args)
{
int iteration = 10;
int ranSleepTime = 1000;
var obj = new MyClass();
var threads = new Thread[3];
(threads[0] = new Thread(() =>
{
Random random = new System.Random();
for (int i = 0; i < iteration; i++)
{
obj.MyMethod("my string 1");
Thread.Sleep(random.Next(ranSleepTime));
}
})).Start();
(threads[1] = new Thread(() =>
{
Random random = new System.Random();
for (int i = 0; i < iteration; i++)
{
obj.MyMethod("my string 2");
Thread.Sleep(random.Next(ranSleepTime));
}
})).Start();
(threads[2] = new Thread(() =>
{
Random random = new System.Random();
for (int i = 0; i < iteration; i++)
{
obj.MyMethod("my string 3");
Thread.Sleep(random.Next(ranSleepTime));
}
})).Start();
foreach (Thread thread in threads)
{
thread.Join();
}
obj.Close(false);
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
Desired look:
for(int i=0;i<3;i++){
threads[i] = new Thread(func); // func is the lambda function
threads[i].Start(myData[i]); // myData[] may be a string array
}
The error message seems to indicate that you are attempting to use an instance member from a static method somewhere. Naturally that is not allowed since a static method does not have a this reference. Here is how I would refactor your code.
public static void Main()
{
string[] myData = GetStringArray();
int iteration = 10;
int ranSleepTime = 1000;
var obj = new MyClass();
var threads = new Thread[myData.Length];
for (int i = 0; i < threads.Length; i++)
{
int captured = i; // This is required to avoid capturing the loop variable.
threads[i] = new Thread(
() =>
{
var random = new Random();
for (int i = 0; i < iteration; i++)
{
obj.MyMethod(myData[captured]);
Thread.Sleep(random.Next(ranSleepTime));
}
});
threads[i].Start();
}
foreach (Thread thread in threads)
{
thread.Join();
}
obj.Close(false);
}
I must mention, however, that creating new threads in an unbounded loop is generally undesirable. If the loop has a tight bound then maybe, but I would have to get a better understanding of the problem before making any further comments regarding this point.