C# garbage collecting reasons? - c#

I have the following code as a WPF app.
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace TestLeak {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
Random RND = new Random();
int SIZE = 100000;
double fValue0 = 0;
double fValue1 = 0;
double fValue2 = 0;
JArray aValues0 = new JArray(new double[SIZE]);
JArray aValues1 = new JArray(new double[SIZE]);
JArray aValues2 = new JArray(new double[SIZE]);
JArray aValues = new JArray();
aValues.Add(aValues0);
aValues.Add(aValues1);
aValues.Add(aValues2);
DispatcherTimer oTimer = new DispatcherTimer(DispatcherPriority.Normal);
oTimer.Tick += new EventHandler((oSender, aArgs) => {
for (int i = 0; i < SIZE; i++) {
fValue0 += 1;
fValue1 += 1;
fValue2 += 1;
aValues0[i] = fValue0;
aValues1[i] = fValue1;
aValues2[i] = fValue2;
}
});
oTimer.Interval = TimeSpan.FromMilliseconds(1000);
oTimer.Start();
}
}
}
I have no idea why the GC needs to work that hard, what is it collecting? It's just basic assignment and overwriting (kind of an)array values. Could it be an issue with NewtonSoft Jarray objects?
The issue is that for my app, the interval is way smaller (aiming for ~16ms) but on each step the GC alone takes 40+ms to complete.
Thank you!
Garbage Collection at work

You are creating 300k objects every tick because JArray.operator[] is of type JToken, which is a reference class. You're assigning doubles to them for every item of every one of your three arrays, which implicitly creates JValue instances:
public static implicit operator JToken(double value)
{
return new JValue(value);
}
That's what the garbage collector is collecting.

Related

How can I make a textBox print a variable in between a certain text?

For example, I need richTextBox2 to print whatever is in between "AaBb" and "CcDd" at richTextBox1.
if (richTextBox1.Text.Contains ("AaBb x CcDd"))
//print whatever is x in richTextBox2
Edit: I forgot to mention what i'm trying to do. I´m trying to scrape a website and print the value in the richTextBox (Euro to Dollar for example).
This is my code so far. Unfortunnaly, it doesn't work on both answers.
Version 1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Net;
using System.Windows.Forms;
namespace BitPrice
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
WebClient priceVariationDollar = new WebClient();
string dollarPrice = priceVariationDollar.DownloadString("https://www.xe.com/pt/currencyconverter/convert/?Amount=1&From=EUR&To=USD");
euroTextBox.Text = dollarPrice;
if (euroTextBox.Text.Contains("<span class=converterresult - toAmount></span>"));
{
int p1, p2;
p1 = euroTextBox.Text.IndexOf("<Span class=converterresoult - toAmount>");
p2 = euroTextBox.Text.IndexOf("</span>");
if (p2 > p1 + 4)
{
dollarTextBox.Text = euroTextBox.Text.Substring(p1 + 4, p2 - p1 - 4);
}
}
}
}
Version 2:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Net;
using System.Windows.Forms;
namespace BitPrice
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
WebClient priceVariationDollar = new WebClient();
string dollarPrice = priceVariationDollar.DownloadString("https://www.xe.com/pt/currencyconverter/convert/?Amount=1&From=EUR&To=USD");
euroTextBox.Text = dollarPrice;
if (euroTextBox.Text.Contains("<span class=converterresult - toAmount></span>"));
{
var startIndex = euroTextBox.Text.IndexOf("<span class=converterresult - toAmount>") + "<span class=converterresult - toAmount>".Length;
var endIndex = euroTextBox.Text.IndexOf("</span>");
if (startIndex >= 0 && endIndex > startIndex)
dollarTextBox.Text = euroTextBox.Text.Substring(startIndex, endIndex - startIndex);
}
}
}
Sorry if it´s too long
var startIndex = richTextBox1.Text.IndexOf("AaBb") + "AaBb".Length;
var endIndex = richTextBox1.Text.IndexOf("CcDd");
if (startIndex >= 0 && endIndex > startIndex)
richTextBox2.Text = richTextBox1.Text.Substring(startIndex, endIndex - startIndex);
You will need to first check whether these two text are in richTextBox1, then if they both exit, you see if the first one comes before the second, then you take what is between.
int p1, p2;
string t1, t2;
t1 = "....."; //Your first searched text
t2 = "..."; //Your second searched text
p1 = richTextBox1.Text.IndexOf(t1);
p2 = richTextBox1.Text.IndexOf(t2);
if (p2 > p1 + t1.Length)
richTextBox2.Text1 = richTextBox1.Text.Substring(p1 + t1.Length, p2 - p1 - t1.Length);

I try to find nearest double in Array

I try to follow the code here:
C# Finding Nearest Number in Array
but fail.
The only different from my code with the code there is in my code the MinBy is error (there is red underline) which show its an error in Visual Studio.
By the way, this is the the code that I write:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
double[] array = new double[5] { 0.25, 0.4, 0.5, 0.6, 0.7 };
double TargetNumber = Double.Parse(textBox1.Text);
var nearest = array.MinBy(x => Math.Abs((long)x - targetNumber));
label1.Text = nearest.ToString();
}
}
}
Im new with C# things. Sorry for a noob question.
Thanks in advance.
You overcomplicate things. Here is your "bread-and-butter" helper method which finds the value from array a nearest to the passed value d:
private static double? FindNearestValue(IEnumerable<double> arr, double d)
{
var minDist = double.MaxValue;
double? nearestValue = null;
foreach (var x in arr)
{
var dist = Math.Abs(x - d);
if (dist < minDist)
{
minDist = dist;
nearestValue = x;
}
}
return nearestValue;
}
To use it:
private void button1_Click(object sender, EventArgs e)
{
double[] array = new double[5] { 0.25, 0.4, 0.5, 0.6, 0.7 };
double TargetNumber = Double.Parse(textBox1.Text);
var nearest = FindNearestValue(array, TargetNumber);
label1.Text = nearest.ToString(); // nulls are printed as empty string
}
For small arrays linear search has comparable speed to the binary search. If implementing binary search is problem for you and you're new to c# (didn't get used to LINQ power) then good-ol' foreach is your friend for now.
Sometimes implementing a library to use just one method sounds a little bit like an overkill (even if MoreLINQ is an amazing library)... this code should provide you the same result without using an external library, if it's a good solution for you:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Double[] array = new Double[] { 0.25, 0.4, 0.5, 0.6, 0.7 };
Double targ = Double.Parse(textBox1.Text);
Double[] arraySorted = array.OrderBy(x => Math.Abs(x - targ)).ToArray();
Int32 idx = Array.IndexOf(array,arraySorted.First());
label1.Text = idx.ToString();
Double arrayValue = array[idx];
Int32 idxLower = 0;
Int32 idxUpper = 0;
if (targ == arrayValue)
idxLower = idxUpper = idx;
else
{
if (targ > arrayValue)
{
idxLower = idx;
idxUpper = idx + 1;
}
else
{
idxLower = idx - 1;
idxUpper = idx;
}
}
label2.Text = idxLower.ToString();
label3.Text = idxUpper.ToString();
}
}
}

Task doesn't change parameters

I am playing with Task functions and found a pretty strange problem that I run Task in for loop and pass the parameters to function (i) the loop count is 100.
As I expected the output would be like this.
1
2
3
4
5
But the output I get from this function is
100
100
100
I mean it won't change to new parameters. For more details I uploaded the whole project.
Download Sample Program that I made!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;
}
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => button_tast());
}
void button_tast()
{
Task[] tk =new Task[100];
for (int i = 0; i < 100; i++)
{
tk[i] = Task.Factory.StartNew(() => taskThread(i));
}
Task.WaitAll(tk);
}
void taskThread(int i){
listBox1.Items.Add(i);
}
}
}
It's because you're closing over the loop variable. You can rewrite the loop as
for (int i = 0; i < 100; i++)
{
int taskNumber = i
tk[i] = Task.Factory.StartNew(() => taskThread(taskNumber));
}
and you'll be fine
The problem is that from the point of view of the Tasks, the variable i is global, and can be modified in a non-threadsafe manner. This is easily rectified though....
for (int i = 0; i < 100; i++)
{
int localCopy = i;
tk[i] = Task.Factory.StartNew(() => taskThread(localCopy));
}

C# wpf multithreading

I want to generate 3 random number in threads then save it to list. Here's my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.IO;
namespace Multithreading1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
List<int> myList = new List<int>();
int threadNumber = 0;
int currentRecNumber = -1;
public MainWindow()
{
InitializeComponent();
}
void ThreadHandler(int recNumber,int number)
{
Action action = null;
action = () =>
{
myList[recNumber] = number;
++currentRecNumber;
--threadNumber;
if (currentRecNumber < myList.Count)
{
++threadNumber;
Thread t = new Thread(() => GetRandomNumber(currentRecNumber));
t.Start();
}
else
if (threadNumber == 0) //finish
{
List<String> stringList = new List<String>();
for (int i = 0; i < myList.Count;i++)
{
stringList.Add(myList[i].ToString());
}
File.WriteAllLines("C:\\Users\\Public\\Documents\\MyList.txt", stringList);
System.Windows.MessageBox.Show("Finish");
}
};
this.Dispatcher.BeginInvoke(action);
}
void GetRandomNumber(int recNumber)
{
Random rnd = new Random();
int randomInt = rnd.Next(1, 13);
ThreadHandler(recNumber, randomInt);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 20; i++)
{
myList.Add(-1);
}
for (int i = 0; i < 3; i++)
{
++currentRecNumber;
++threadNumber;
Thread t = new Thread(() => GetRandomNumber(currentRecNumber));
t.Start();
}
}
}
}
The problem are:
1. Sometimes it throw ArgumentOutOfRangeException at myList[recNumber] = number;
2. If it get past (1) the resulting file still contain -1s, eg:
-1
-1
8
6
11
-1
1
3
-1
3
3
8
8
8
8
10
10
10
10
12
Anyone know what is wrong ?
Thanks in advance.
Your Dispatcher.BeginInvoke will call each action on the thread the dispatcher is associated with, so you are effectively not actually running the actions on different threads. It might be better to do as much as you can in the ThreadHandler method, and only make UI changes inside the BeginInvoke action.
Also in your button1_Click, you increment currentRecNumber before you start each thread, so that will cause the first few threads to skip the first few items in the list.
You also have a major issue because you are accessing shared variables (currentRecNumber, threadNumber, and myList) from different threads, which can cause all manner of threading issues. You need to use some sort of synchronisation to ensure that each thread is reading and writing the correct values from these variables. You can use the InterlockedIncrement and InterlockedDecrement to mitigate some of these issues, but not all of them.
I'll also point out that creating threads is expensive, it's much better to schedule the work you want doing on thread pool threads , use a BackgroundWorker, or use one of the parallelism libraries, like the Task Parallel Library or PLINQ.
I would recommend having a read of this free ebook on threading by Joe Albahari.
Thanks Matt for the ebook. It's very easy to understand. I managed to fix my code with minor addition. The key of its problem is "Lambda expressions and captured variables", so I add couple local variables to it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.IO;
namespace Multithreading1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
List<int> myList = new List<int>();
int threadNumber = 0;
int currentRecNumber = -1;
public MainWindow()
{
InitializeComponent();
}
void ThreadHandler(int recNumber,int number)
{
Action action = null;
action = () =>
{
myList[recNumber] = number;
++currentRecNumber;
--threadNumber;
int localCurrentRecNumber = currentRecNumber;
int localThreadNumber = threadNumber;
if (localCurrentRecNumber < myList.Count)
{
++threadNumber;
Thread t = new Thread(() => GetRandomNumber(localCurrentRecNumber));
t.Start();
}
else
if (localThreadNumber == 0) //finish
{
List<String> stringList = new List<String>();
for (int i = 0; i < myList.Count;i++)
{
stringList.Add(myList[i].ToString());
}
File.WriteAllLines("C:\\Users\\Public\\Documents\\MyList.txt", stringList);
System.Windows.MessageBox.Show("Finish");
}
};
this.Dispatcher.BeginInvoke(action);
}
void GetRandomNumber(int recNumber)
{
Random rnd = new Random();
int randomInt = rnd.Next(1, 13);
ThreadHandler(recNumber, randomInt);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 20000; i++)
{
myList.Add(-1);
}
for (int i = 0; i < 3; i++)
{
++currentRecNumber;
++threadNumber;
int localCurrentNumber = currentRecNumber;
Thread t = new Thread(() => GetRandomNumber(localCurrentNumber));
t.Start();
}
}
}
}

Keep getting this error: The event 'System.Windows.Controls.Primitives.ToggleButton.Checked' can only appear on the left hand side of += or -=

I keep getting this error when making the program as given below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace simplecalc
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
int a, b, c;
a = int.Parse(textBox1.Text);
b = int.Parse(textBox2.Text);
if (rbadd.Checked == true)
c = a + b;
else if (rbsubtract.Checked == true)
c = a - b;
else if (rbdivide.Checked == true)
c = a / b;
else
c = a * b;
textBox3.Text = c.ToString();
}
}
}
I am in the process of making a basic calculator in C# in WPF. I am very new to C#.
Checked here is an event, not a bool, that happens when it is checked. You need a different property - presumably IsChecked.
Minor note, but stylistically, it is usually preferable not to compare booleans to true/false, but rather:
if (rbadd.IsChecked)
c = a + b;
else if (rbsubtract.IsChecked)
c = a - b;
else if (rbdivide.IsChecked)
c = a / b;
etc; or if you wanted to test for false: if(!rbadd.IsChecked).

Categories

Resources