I am teaching myself how to operate with large numbers in complex loops.
In the main program, it will calling an method to perform some action.
In the example that I am working on it is just displaying the time in seconds.
As I am working the Form goes to Not Responding and crashes.
The screen looks like
When the program is running, every second would be outputted to the screen letting the user see that the program is still running and not responding.
The code is as follows
private void BtnStart_Click(object sender, EventArgs e)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
label1.Text = "Start";
label2.Text = "Started";
dataGridView1.ColumnCount = 1;
dataGridView1.Columns[0].Name = "Number";
for (int index1 = 0; index1 < limit; index1++)
{
for (int index2 = 0; index2 < limit; index2++)
{
for (int index3 = 0; index3 < limit; index3++)
{
if ((stopwatch.ElapsedMilliseconds % 1000) == 0)
{
timeCount++;
AddRowToDG();
}
count++;
}
}
}
label1.Text = "The count is " + count.ToString();
// Stop.
stopwatch.Stop();
Double myTime = stopwatch.ElapsedMilliseconds;
label2.Text = (myTime / 1000).ToString();
}
private void AddRowToDG()
{
dataGridView1.Rows.Add(timeCount.ToString());
}
If I use above 150 for the limit, the program goes to not responding.
In the programming that I will be actually using will be 10 to power of 12.
From the research that I have done, there is tasks and threads that can be used.
Which methodology should I use and where would I get the best resource to help me to make the choices in future?
C# language have System.Threading.Tasks.Task and System.Threading.Thread classes, but for Windows Forms you should use System.ComponentModel.BackgroundWorker. There is DoWork event to do your application logic in the different thread.
Related
I have a very specific and demanding workload I am trying to multithreaded. This is very new to me so I am struggling to find an effective solution.
Program Description: UpdateEquations() is cycling through a list of mathematical functions to update the coordinates of rendered lines. By default, func.Count = 3, so this will call CordCalc() 1500 times every frame. I am using NClac to parse a function string and write the result to the Function list, which will later be used before the end of the frame (irrelevant).
Goal: I want to put each cycle of the for(int a) loop inside its own thread. Since for(int a) will only loop 3 times, I just need to start three threads. I cannot continue the for(int i) loop until for(int a) is fully calculated. I am calculating a very large about of small tasks so it would be too expensive to assign each task to the thread.
What I am currently trying to do: I am trying to use a ThreadPool queue, however I'm not sure how to wait for them all to finish before continuing onto the next for(int i) iteration. Furthermore, while the program compiles and executes, the performance is disastrous. Probably %5 of my original performance. I am not sure if creating a "new WaitCallback" is expensive or not. I was looking for a way to predefined threads somehow so that I don't have to reinitialize them 1500 times a frame. (Which is what I suspect the issue is).
Other things I've tried: I tried using new Thread(() => CordCalc(a, i)); however this seemed to have much worse performance. I saw online somewhere that using a ThreadPool would be less expensive.
(This code is shortened for readability and relevance)
public List<Function> func;
private Expression[] exp;
private int lines_i;
private int lines_a;
public void Start()
{
func = new List<Function>();
exp = new Expression[func.Count];
for (int i = 0; i < func.Count; i++) exp[i] = new Expression(func[i].function);
}
//Calculate
public void CordCalc(object state)
{
for (int b = 0; b < func.Count; b++)
exp[lines_a].Parameters[func[b].name] = func[b].mainCords[lines_i - 1];
exp[lines_a].Parameters["t"] = t;
try
{
func[lines_a].mainCords[lines_i] = Convert.ToSingle(exp[lines_a].Evaluate());
}
catch
{
Debug.Log("input Error");
func[lines_a].mainCords[lines_i] = 0;
}
}
private void UpdateEquations()
{
//Initialize equations
for (int a = 0; a < func.Count; a++)
{
func[a].mainCords[0] = t;
}
lines_i = 1;
for (int i = 1; i < 500; i++)
{
lines_a = 0;
for (int a = 0; a < func.Count; a++)
{
//Calculate
ThreadPool.QueueUserWorkItem(new WaitCallback(CordCalc));
//This was something else that I tried, which gave worse results:
//threads[a] = new Thread(() => CordCalc(a, i));
//threads[a].Start();
//t.Join();
//This was my original method call without multithreading
//func[a].mainCords[i] = CordCalc(a, i);
lines_a++;
}
lines_i++;
}
private void FixedUpdate()
{
t += step * (2 + step) * 0.05f;
UpdateEquations();
}
//Function List
public class Function
{
public string name;
public string function;
public float[] mainCords;
//Constructor
public Function(string nameIn, string funcIn)
{
name = nameIn;
function = funcIn;
}
public void SetSize(int len)
{
mainCords = new float[len];
}
}
I am trying to create a console application similar to speedsum site. The speedsum is a website which is really useful and fun to test our own mathematical ability in 30s.
After giving few try-s I was just thought to create one small C# console application with same concept.
Following is my code which is working fine. But I could not display countdown ?!
My code:
static void Main(string[] args)
{
int testCount = 0;
Console.Write("\n Get.. Set... Go.... : This is a 30s test.. " +
"Once each problem is completed the time finished will be shown \n Good Luck.. :) \n \n");
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 1; i < 100000; i++)
{
if (watch.Elapsed.TotalSeconds >= 30)
break;
TimeSpan timeSpan = TimeSpan.FromSeconds(Convert.ToInt32(watch.Elapsed.TotalSeconds));
Console.Write($"\n {timeSpan.ToString("c")}" );
Random r = new Random();
int number1 = r.Next(10);
int number2 = r.Next(10);
int operation = r.Next(4);
var method = (operation > 2) ? '+' : '*';
int result = 0;
result = method == '+' ? (number1 + number2) : (number1 * number2);
Console.Write($" \n {number1} {method} {number2} = ");
var getAnswer = Convert.ToInt32(Console.ReadLine());
if (result == getAnswer)
{
testCount++;
continue;
}
else
break;
}
watch.Stop();
if(testCount >= 1 && testCount <=5)
Console.Write($"\n No Worries!! Try Hard ... \n you have solved {testCount} problems \n");
else if(testCount >=6 && testCount <=10)
Console.Write($"\n Good!! You can do well next time ... \n you have solved {testCount} problems \n");
else
Console.Write($"\n Awesome!! You are really a Genius ... \n you have solved {testCount} problems \n");
Console.Write("\n Thank you for playing with me... \n Enter a key to exit");
Console.Read();
}
I would like to get the countdown from 30s to 0s at,
Get.. Set... Go.... : This is a 30s test.. Once each problem is completed the time finished will be shown
Good Luck.. :)
<<Timer Should go here>> (30, 29... 0)
5 * 5 = 25 ...
This SO Question Showing how to get countdown into our program, But I am confused at how I can do both parallely countdown and giving problems.
Any suggestion would be helpful to me.
It looks like you want to use BackgroundWorker. Then, DoWork event will decrement amount of seconds left, while ProgressChanged event will report current progress. The advantage of this solution is that background worker is running async, so you will not block your main thread allowing the user to enter answer anytime they want.
private static int secondsLeft;
private static BackgroundWorker bgWorker;
static void Main(string[] args)
{
secondsLeft = 30;
bgWorker = new BackgroundWorker();
bgWorker.DoWork += bgWorker_DoWork;
bgWorker.ProgressChanged += bgWorker_ProgressChanged;
bgWorker.WorkerReportsProgress = true;
bgWorker.RunWorkerAsync();
Console.ReadLine();
}
private static void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (secondsLeft >= 0)
{
bgWorker.ReportProgress(secondsLeft);
Thread.Sleep(1000);
secondsLeft--;
}
}
private static void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine($"Seconds left: {e.ProgressPercentage}");
}
I want to create an array of BackgroundWorkers which work alongside each other to take advantage of multicore processors. Let's say I want eight of them working simultaneously. I also want a separate Timer thread to report in the GUI on some data which each of the threads has been processing.
My problem is this. It takes around 3-4 seconds for each worker to start work. So the first worker element in the array starts straight away. The second starts a few seconds after. The third starts a few seconds after that etc. etc.
I want them all to start straight away. How can I fix this?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
BackgroundWorker[] bw;
int threads = 8;
data[] d;
private void Form1_Load(object sender, EventArgs e)
{
d = new data[threads];
for (int i = 0; i < threads; i++) d[i] = new data(i);
bw = new BackgroundWorker[threads];
for (int i = 0; i < threads; i++)
{
bw[i] = new BackgroundWorker();
bw[i].DoWork += new DoWorkEventHandler(Work);
}
timer1.Enabled = true;
for (int i = 0; i < threads; i++) bw[i].RunWorkerAsync(d[i]);
}
private void Work(object sender, DoWorkEventArgs e)
{
data o = (data)e.Argument;
while (true) o.count += o.id;
}
private void timer1_Tick(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
long total = 0;
for (int n = 0; n < threads; n++) {
sb.Append(d[n].id + ": " + d[n].count + "\n");
total+=d[n].count;
}
sb.Append("TOTAL: "+total);
richTextBox1.Text = sb.ToString();
}
}
public class data {
public int id;
public long count;
public data(int id)
{
this.id = id;
this.count = 0;
}
}
-------------------------------EDIT: Found out later than the 3-4 second delay only applies beyond the maximum number of logical cores you have. So if you have 20 cores, and set 20 threads that's fine. However, if you have 4 cores, and set 20 threads, there will a delay between creating each of the 16 threads beyond the first 4.
I want them all to start straight away.
Then Backgroundworkers are not the right tool. And maybe even Windows is not the right OS.
Backgroundworkers run on the ThreadPool, the guideline is to use that only for short (< 500ms) tasks. The Threadpool creates new threads at 2/second (roughly).
The short solution is to increase ThreadPool.Minthreads (look up the actual name/method) but that's still a whacky solution.
You did not provide enough (real) information for a better advice.
I suppose, that the line while (true) o.count += o.id; consumes so much CPU that other operations may be blocked.
Try to add Thread.Sleep(100); before o.count += o.id; or reduce the number of threads (8 threads + GUI thread => 9 Threads just for your application).
I am currently writing a program which requires me to have a pause between executing tasks.
So I have 4 things.
Read Limit
Delay Between Each Read
Total Reads
Global delay (pause the program for 'x' seconds after a task is finished)
Basically, one task is considered the "Read Limit". So, for example, if I have these settings:
Read Limit (10)
Delay Between Each Read (20)
Total Reads (100)
Global Delay (30)
The program has to read 10 lines from the file based on "Read Limit" and between reading each line, there is a delay of 20 seconds based on "Delay Between Each Read". After it reads 10 lines, it is paused for 30 seconds based on "Global Delay". When the global delay is over, it starts again where it stopped and continues doing this until the limit of 100 is reached based on "Total Reads".
I have tried using System.Threading.Thread.Sleep() but I couldn't make it work. How can I achieve this with C#?
Thanks in advance.
//update with some of my code.
I load the file like this:
private void btnLoadFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
string[] lines = System.IO.File.ReadAllLines(ofd.FileName);
}
}
I have 4 global variables:
public int readLimit = 0;
public int delayBetweenRead = 0;
public int totalReads = 0;
public int globalDelay = 0;
public int linesRead = 0;
And I want to make the function like this:
private void doTask()
{
while (linesRead <= readLimit)
{
readLine(); // read one line
doDelay(); // delay between each line
readLine(); // read another line and so on, until readLimit or totalReads is reached
globalDelay(); // after readLimit is reached, call globalDelay to wait
linesRead++;
}
}
This might be of interest - here's the way to do this with Microsoft's Reactive Framework (NuGet "Rx-Main").
int readLimit = 10;
int delayBetweenRead = 20;
int globalDelay = 30;
int linesRead = 100;
var subscription =
Observable
.Generate(0, n => n < linesRead, n => n + 1, n => n,
n => TimeSpan.FromSeconds(n % readLimit == 0 ? globalDelay : delayBetweenRead))
.Zip(System.IO.File.ReadLines(ofd.FileName), (n, line) => line)
.Subscribe(line =>
{
/* do something with each line */
});
If you need to stop the reading before it finishes naturally just call subscription.Dispose();.
What you do you mean by
I have tried using System.Threading.Thread.Sleep() but I couldn't make it work
Here is an example of achieving what you described with Thread.Sleep:
using (var fs = new FileStream("C:\\test.txt", FileMode.Open, FileAccess.Read))
{
using (var sr = new StreamReader(fs))
{
int nRead = 0;
while (nRead < settings.Total)
{
for (int i = 0; i < settings.ReadLimit && nRead < settings.Total; ++i, nRead++)
{
Console.WriteLine(sr.ReadLine());
if (i + 1 < settings.ReadLimit)
{
Thread.Sleep(settings.Delay * 1000);
}
}
if (nRead < settings.Total)
{
Thread.Sleep(settings.GlobalDelay * 1000);
}
}
}
}
Did anyone tried to find out - what is faster and what is more efficient (less objects created and thus less GC is involved) - control.BeginInvoke or SynchroniseContext.Post ?
WPF, C#, .NET 4
I'd appreciate responses with practical backing rather than "I think" or "I heard somewhere"..
Cheers
P.S. I am going to post a number of messages to few controls and I want it to be max efficient and fast (few hundred updates / sec). I know .NET can handle this (I did it before) but now I want it to be as fast as possible...
Firstly, there is no Control.BeginInvoke in WPF (that's winforms you're thinking of). Secondly, SynchronizationContext is an abstraction over whatever synchronization mechanism the current platform provides. In the case of WPF, it's an abstraction over the Dispatcher. Theoretically you pay a small price for using the abstraction rather than directly using the Dispatcher. But the abstraction is there for a good reason - sometimes you need to write thread synchronization code that is independent of the platform. If you don't then by all means use the Dispatcher directly.
The BeginInvoke is 42.8% faster than SynchronizationContext.Post on my i7 desktop.
The results are:
Post Send Diff ms Ratio
1280866 925416 35.00 -38.4%
1192232 916251 27.00 -30.1%
1338990 876215 46.00 -52.8%
1394783 863241 53.00 -61.6%
1332485 1046789 28.00 -27.3%
1335241 895784 43.00 -49.1%
1267470 1064894 20.00 -19.0%
1308461 884136 42.00 -48.0%
1321243 850704 47.00 -55.3%
1313230 896469 41.00 -46.5%
The code :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;
}
Thread th;
DispatcherSynchronizationContext ctx;
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
Thread.CurrentThread.Priority = ThreadPriority.Highest;
ctx = new DispatcherSynchronizationContext(this.Dispatcher);
th = new Thread(Start);
th.Start();
}
int MACRO = 10;
int TESTS = 10;
int LOOPS = 50000;
void Start()
{
Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
// flush just in case
for (int i = 0; i < 100; i++)
{
ctx.Post(Callback, 9999999);
this.Dispatcher.BeginInvoke(
new Action<object>((object state) => { txt2.Text = state.ToString(); }),
DispatcherPriority.Send, 9999999);
}
Thread.Sleep(1000);
// results
List<Tuple<long, long>> results = new List<Tuple<long, long>>();
// actual test
for (int x = 0; x < MACRO; x++)
{
Stopwatch sw = new Stopwatch();
// sync context post
long tick1, tick2;
for (int i = 0; i < TESTS; i++)
{
sw.Start();
for (int j = i; j < LOOPS + i; j++)
{
ctx.Post(Callback, j);
}
sw.Stop();
Thread.Sleep(1500);
}
tick1 = sw.ElapsedTicks;
// begin invoke
sw.Reset();
for (int i = 0; i < TESTS; i++)
{
sw.Start();
for (int j = i; j < LOOPS + i; j++)
{
this.Dispatcher.BeginInvoke(
new Action<object>((object state) => { txt2.Text = state.ToString(); }),
DispatcherPriority.Normal, j);
}
sw.Stop();
Thread.Sleep(1500);
}
tick2 = sw.ElapsedTicks;
// store results
results.Add(new Tuple<long, long>(tick1, tick2));
// display to make it less boring
this.Dispatcher.BeginInvoke(new Action(() => { txt3.Text += string.Format("{0} {1}. ", tick1, tick2); }));
Thread.Sleep(100);
}
StringBuilder sb = new StringBuilder();
foreach (var res in results)
sb.AppendLine(string.Format("{0}\t{1}\t{2:0.00}\t{3:0.0%}",
res.Item1, res.Item2, (res.Item1 - res.Item2) / 10000, res.Item2 != 0 ? 1.0 - res.Item1 / (double)res.Item2 : 0.0));
this.Dispatcher.BeginInvoke(
new Action(() => { txb1.Text = sb.ToString(); }));
}
void Callback(object state)
{
txt1.Text = state.ToString();
}
}