array of threads c# - c#

i have this code:
Thread[] threadsArray = new Thread[4];
for (int i = 0; i < 4; i++)
{
threadsArray[i] = new Thread(() => c1.k(i));
}
for (int i = 0; i < 4; i++)
{
threadsArray[i].Start();
}
for (int i = 0; i < 4; i++)
{
threadsArray[i].Join();
}
the function k is this:
void k(int i)
{
while(true)
Console.WriteLine(i);
}
for some reason just the last thread is running and printing 4444444....
why aren't all the threads running?

All of the threads are printing the same variable.
Your lambda expression (() => c1.k(i)) captures the i variable by reference.
Therefore, when the lambda expression runs after i++, it picks up the new value of i.
To fix this, you need to declare a separate variable inside the loop so that each lambda gets its own variable, like this:
for (int i = 0; i < 4; i++)
{
int localNum = i;
threadsArray[i] = new Thread(() => c1.k(localNum));
}

You are closing over the i variable.
Try this instead
for (int i = 0; i < 4; i++)
{
int x = i;
threadsArray[i] = new Thread(() => c1.k(x));
}

Thread[] threadsArray = new Thread[4];
for (int i = 0; i < 4; i++)
{
//better use ParameterizedThreadStart Delegate
threadsArray[i] = new Thread(k);
}
for (int i = 0; i < 4; i++)
{
//passing the value to the function
threadsArray[i].Start(i);
}
for (int i = 0; i < 4; i++)
{
threadsArray[i].Join();
}
//changing the input data type
void k(object i)
{
while (true)
Console.WriteLine((int)i);
}

Related

2d_array random numbers (10Rows, 6 COLS) not repeated to file C#

I need to streamwrite into a file.txt a 10 random numbers combinations (NOT REPEATED) like lottery program. I got everything except Non-repeated random numbers. it has to be seen (file.txt) like a 2D array with 10 combinations thx.
class Matriz
{
private int[,] array;
private int nfilas, ncols;
public void Ingresar()
{
Random aleatori = new Random();
nfilas = 10;
ncols = 6;
Console.WriteLine("\n");
array = new int[nfilas, ncols];
for (int filas = 0; filas < nfilas; filas++)
{
for (int columnas = 0; columnas < ncols; columnas++)
array[filas, columnas] = aleatori.Next(0, 50);
}
}
public void Imprimir()
{
StreamWriter fitxer = new StreamWriter(#"C:\andres\lotto649.txt");
int contador = 0;
for (int f = 0; f < nfilas; f++)
{
for (int c = 0; c < ncols; c++)
fitxer.Write(array[f, c] + " ");
fitxer.WriteLine();
contador++;
}
fitxer.WriteLine($"\n\n\tHay {contador} combinaciones de la Loteria 6/49");
fitxer.Close();
}
static void Main(string[] args)
{
Matriz array_menu = new Matriz();
array_menu.Ingresar();
array_menu.Imprimir();
}
}
Something like this should work.
Before inserting the new number in the given position, check the row thus far if the same number is already in there and if so, repeat the process until you get a number that isn't yet in there.
for (int filas = 0; filas < nfilas; filas++)
{
for (int columnas = 0; columnas < ncols; columnas++)
{
bool cont = true;
while(cont)
{
cont = false;
int newRand = aleatori.Next(0, 50);
for(int i = 0; i < columnas; i++)
if(array[filas, i] == newRand)
cont = true;
if(cont)
continue;
array[filas, columnas] = newRand;
break;
}
}
}
Alternatively, since the number is small you could also work with a list of ints and remove the given value from there.
This has the advantage, that you'll never have to redo your random number as it will always produce a valid result. The above example could (theoretically) run indefinitely long.
for (int filas = 0; filas < nfilas; filas++)
{
List<int> nums = new List<int>(49);
for(int i = 0; i < 49; i++)
nums.Add(i + 1); //num 1...49
for (int columnas = 0; columnas < ncols; columnas++)
{
int index = aleatori.Next(0, nums.Count)
array[filas, columnas] = nums[index];
nums.RemoveAt(index);
}
}

Code execution stops after for loop?

So i'm trying to make a program that uses the League of Legends API in C#.
I found a NuGet package that makes using the API a lot easier.
Everything works fine so far except the code execution stops after the
first for loop i use.
Here's the code: (of course i took out the api key)
string[] summnames;
long[] champids;
long[] teamids;
long[] champs;
CreepScoreAPI.ParticipantLive[] enemy;
CreepScoreAPI.ParticipantLive[] ally;
CreepScoreAPI.ParticipantLive centsumm;
CreepScoreAPI.ParticipantLive[] champsss;
CreepScoreAPI.ChampionStatic[] champions;
CreepScoreAPI.Summoner[] sumners;
CreepScoreAPI.League[] leaguesz;
Dictionary<string, List<CreepScoreAPI.League>>[] leagues;
int[] champidsint;
string[] champnames;
int s;
int se;
public async Task<string> game(string summname)
{
string data;
CreepScoreAPI.CreepScore cs = new CreepScoreAPI.CreepScore("api key");
var summoner = await cs.RetrieveSummoner(CreepScoreAPI.CreepScore.Region.EUNE, summname);
long summid = summoner.id;
var thegame = await summoner.RetrieveCurrentGameInfo();
CreepScoreAPI.ParticipantLive[] participants = thegame.participants.ToArray();
for (int i = 0; i <= 9; i++) { summnames[i] = participants[i].summonerName;}
for (int i = 0; i <= 9; i++) { champids[i] = participants[i].championId;}
for (int i = 0; i <= 9; i++) { teamids[i] = participants[i].teamIdLong;}
for (int i = 0; i <= 9; i++) { champids[i] = participants[i].championId;}
for (int i = 0; i <= 9; i++) { champidsint[i] = Convert.ToInt32(champids[i]);}
for (int i = 0; i <= 9; i++) { champions[i] = await cs.RetrieveChampionData( CreepScoreAPI.CreepScore.Region.EUNE, champidsint[i], CreepScoreAPI.Constants.StaticDataConstants.ChampData.All, "en_US", "7.1.1",false ); }
for (int i = 0; i <= 9; i++) { champnames[i] = champions[i].name; }
for (int i = 0; i <= 9; i++) { sumners[i] = await cs.RetrieveSummoner(CreepScoreAPI.CreepScore.Region.EUNE, summnames[i]); }
for (int i = 0; i <= 9; i++) { leagues[i] = await sumners[i].RetrieveLeague(); }
/* teamsorter */
foreach (CreepScoreAPI.ParticipantLive p in participants)
{
if (p.summonerId == summid)
{
centsumm = p;
}
if (p.teamIdLong == centsumm.teamIdLong)
{
ally[s] = p;
s++;
}
if (p.teamIdLong != centsumm.teamIdLong)
{
enemy[se] = p;
se++;
}
}
data = " I'LL FORMAT A STRING THAT OUTPUTS ALL THE DATA I NEED HERE";
return data;
}
When I call the game function and input the name of the summoner i gets to the first for loop and doesn't even populate the summnames[] array and stops execution with no error code.
What I'm trying to do with all the loops is populate the variables I made before the function so I can use them later for other purposes.
I think you should assign all the arrays and set their length to at least 10.
This could solve the problem.

Count how many items in a DataTable

I have this form where textboxes holds a client's education information. I've put these textboxes in array so I can individually call them and put information to them from my datatable. I achieve this using a for loop and counter for it is the amount of rows in the datatable. I was wondering if there's a way to count the amount of items in it so I can change the counter to a much larger value and avoid all these other counters:
TextBox[] arrayE = {
txtSchoolN1, txtDegree1, txtStartD1, txtEndD1,
txtSchoolN2, txtDegree2, txtStartD2, txtEndD2,
txtSchoolN3, txtDegree3, txtStartD3, txtEndD3,
txtSchoolN4, txtDegree4, txtStartD4, txtEndD4,
txtSchoolN5, txtDegree5, txtStartD5, txtEndD5,
txtSchoolN6, txtDegree6, txtStartD6, txtEndD6,
};
int[] counter = { 0, 1, 2, 3 };
for (int x = 0; x < dataTable.Rows.Count; x++)
{
arrayE[counter[0]].Text = dataTable.Rows[x][0].ToString().Trim();
arrayE[counter[1]].Text = dataTable.Rows[x][1].ToString().Trim();
arrayE[counter[2]].Text = dataTable.Rows[x][2].ToString().Trim();
arrayE[counter[3]].Text = dataTable.Rows[x][3].ToString().Trim();
counter[0] += 4;
counter[1] += 4;
counter[2] += 4;
counter[3] += 4;
}
In a nutshell, I'm trying to shorten my code
Use a second, nested loop:
int[] counter = { 0, 1, 2, 3 };
for (int x = 0; x < dataTable.Rows.Count; x++) {
for (int i = 0; i < counter.Length; i++) {
arrayE[counter[i]].Text = dataTable.Rows[x][i].ToString().Trim();
counter[i] += 4;
}
}
Or, without the counter array:
for (int x = 0; x < dataTable.Rows.Count; x++) {
for (int y = 0; y < 4; i++) {
arrayE[4 * x + y].Text = dataTable.Rows[x][y].ToString().Trim();
}
}
Here's one way.
var arrayE = new[]
{
new[] {txtSchoolN1, txtDegree1, txtStartD1, txtEndD1},
new[] {txtSchoolN2, txtDegree2, txtStartD2, txtEndD2},
new[] {txtSchoolN3, txtDegree3, txtStartD3, txtEndD3},
new[] {txtSchoolN4, txtDegree4, txtStartD4, txtEndD4},
new[] {txtSchoolN5, txtDegree5, txtStartD5, txtEndD5},
new[] {txtSchoolN6, txtDegree6, txtStartD6, txtEndD6}
};
for (var x = 0; x < dataTable.Rows.Count; x++)
{
arrayE[x][0].Text = dataTable.Rows[x][0].ToString().Trim();
arrayE[x][1].Text = dataTable.Rows[x][1].ToString().Trim();
arrayE[x][2].Text = dataTable.Rows[x][2].ToString().Trim();
arrayE[x][3].Text = dataTable.Rows[x][3].ToString().Trim();
}
Is this short enough?
int countOne = 0;
for (int x = 0; x < dataTable.Rows.Count; x++)
{
for (int y = 0; y <= 3; y++)
{
arrayE[countOne + y].Text = dataTable.Rows[x][y].ToString().Trim();
}
countOne += 4;
}

Project Euler #23 in C# inefficient code execution time

I have gone through my code and tried to make it as efficient as i can think possible. Still i can not get this program to run all the way through without freezing my box. The maximum amount of time that i have let it run without it freezing it was about 2 hours. I can not believe this did not execute in that amount of time.
Is it an issue with my computer or is this brute force method of solving this problem that inefficient.
What are some ways that i can avoid this type of inefficiency when writing methods in the future?
private void Form1_Load(object sender, EventArgs e)
{
ArrayList listOfAbundantNumbers = new ArrayList();
ArrayList listOfSums = new ArrayList();
long total = 0;
for (int i = 1; i < 20162; i++)
{
if (isAbundandt(i))
{
listOfAbundantNumbers.Add(i);
}
total+=i;
}
for (int i = 1; i < listOfAbundantNumbers.Count; i++)
{
for (int a = 0; a < listOfAbundantNumbers.Count; a++)
{
long temp1 = Convert.ToInt64(listOfAbundantNumbers[i]);
long temp2 = Convert.ToInt64(listOfAbundantNumbers[a]);
long num = temp1 + temp2;
if(listOfSums.Contains(num) == false)
{
listOfSums.Add(num);
}
}
}
for (int i = 1; i < listOfAbundantNumbers.Count; i++)
{
long temp1 = Convert.ToInt64(listOfAbundantNumbers[i]);
total -= temp1;
}
printLn(total + "");
}
private ArrayList divisorList(long input)
{
ArrayList divisors = new ArrayList();
for (long i = 2; i < Math.Round(Math.Sqrt(input),0,0); i++)
{
long temp = input % i;
if (temp == 0)
{
divisors.Add(i);
divisors.Add(input / i);
}
}
return divisors;
}
private Boolean isAbundandt(long input)
{
long sum = 0;
ArrayList divisor = divisorList(input);
for (int i = 0; i < divisor.Count; i++)
{
long temp1 = Convert.ToInt64(divisor[i]);
sum += temp1;
}
sum++;
if (sum > input)
{
return true;
}
return false;
}
Avoid using ArrayList, prefer generic collection such as List<Int64> because you conversion may be quite expensive.
There is a part in your program which is in O(n^3). It can be reduce to O(n^2) easily. Just replace the following code (O(n) because of List<T>.Contains):
if(listOfSums.Contains(num) == false)
{
listOfSums.Add(num);
}
by:
listOfSums.Add(num);
where listOfSums is now a HashSet<Int64> (it's used to have a collection without duplicates).
Moreover, you can reduce the time for populating the listOfSums by a factor of 2 by just noticing that if you exchange i and a, the sum is the same, then, only one of the two combinations is added to the listOfSums.
You can replace:
for (int i = 1; i < listOfAbundantNumbers.Count; i++)
for (int a = 0; a < listOfAbundantNumbers.Count; a++)
by;
for (int i = 1; i < listOfAbundantNumbers.Count; i++)
for (int a = 0; a <= i; a++)
The final code is:
private static void Main()
{
List<Int64> listOfAbundantNumbers = new List<Int64>();
HashSet<Int64> listOfSums = new HashSet<Int64>();
long total = 0;
for (int i = 1; i < 20162; i++)
{
if (isAbundandt(i))
{
listOfAbundantNumbers.Add(i);
}
total += i;
}
for (int i = 0; i < listOfAbundantNumbers.Count; i++)
for (int a = 0; a <= i; a++)
{
long temp1 = Convert.ToInt64(listOfAbundantNumbers[i]);
long temp2 = Convert.ToInt64(listOfAbundantNumbers[a]);
long num = temp1 + temp2;
listOfSums.Add(num);
}
for (int i = 1; i < listOfAbundantNumbers.Count; i++)
{
long temp1 = Convert.ToInt64(listOfAbundantNumbers[i]);
total -= temp1;
}
Console.WriteLine(total + "");
}
private static List<Int64> divisorList(long input)
{
List<Int64> divisors = new List<Int64>();
for (long i = 2; i < Math.Round(Math.Sqrt(input), 0, 0); i++)
{
long temp = input % i;
if (temp == 0)
{
divisors.Add(i);
divisors.Add(input / i);
}
}
return divisors;
}
private static Boolean isAbundandt(long input)
{
long sum = 0;
List<Int64> divisor = divisorList(input);
for (int i = 0; i < divisor.Count; i++)
{
long temp1 = divisor[i];
sum += temp1;
}
sum++;
if (sum > input)
{
return true;
}
return false;
}

Cannot redraw points which have been set to NULL

I have the following setup:
A TeeChart control with a Colorgrid, and a Points Series added to it:
grid = tChart2.Series[0] as Steema.TeeChart.Styles.ColorGrid;
points = tChart2.Series[1] as Steema.TeeChart.Styles.Points;
To init them, I do:
Random rnd = new Random();
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 128; j++)
{
grid.Add(j, rnd.Next(255), i);
}
}
for (int i = 0; i < 20; i++)
{
double x = rnd.Next();
double y = rnd.Next();
points.Add(x, y);
}
tChart2.Refresh();
And then I have a button on my form:
private void button1_Click(object sender, EventArgs e)
{
Random rnd = new Random();
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 128; j++)
{
grid.YValues[j + 128 * i] = rnd.Next(255);
}
}
for (int i = 0; i < 20; i++)
{
points.SetNull(i);
}
for (int i = 0; i < rnd.Next(20); i++)
{
points.XValues[i] = rnd.Next(128);
points.YValues[i] = rnd.Next(128);
}
points.BeginUpdate();
points.EndUpdate();
}
But the points do not get drawn. When I remove the for-loop containing the SetNull() statement, then they do get drawn, but I want to be able to clear the points (or hide the points don't want to be seen) without using the Points.Clear()/Points.Add(x, y) methodology.
I've also tried each of the following, but there's no difference.
points.TreatNulls = Steema.TeeChart.Styles.TreatNullsStyle.DoNotPaint;
points.TreatNulls = Steema.TeeChart.Styles.TreatNullsStyle.Ignore;
points.TreatNulls = Steema.TeeChart.Styles.TreatNullsStyle.Skip;
Does anyone know how to accomplish this?
Ok, the problem is caused when you set null all of points. You must know if you use method SetNull the point color is set transparent to make invisible the point. Therefore, if you want solve your problem you only need reset the colors of points you want visible, doing SetNull again or change the points color manually and combining the operation with TreatNullsStyle set to Ignore. In my opinion, I think the best option is use SetNull again as I do in next code:
public Form1()
{
InitializeComponent();
InitializeChart();
}
Steema.TeeChart.Styles.ColorGrid grid;
Steema.TeeChart.Styles.Points points;
private void InitializeChart()
{
grid = new ColorGrid(tChart1.Chart);
points = new Points(tChart1.Chart);
tChart1.Aspect.View3D = false;
Random rnd = new Random();
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 128; j++)
{
grid.Add(i, rnd.Next(255), j);
}
}
for (int i = 0; i < 20; i++)
{
double x = rnd.Next(100);
double y = rnd.Next(100);
points.Add(x, y);
}
}
private void button1_Click(object sender, EventArgs e)
{
Random rnd = new Random();
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 128; j++)
{
grid.YValues[j + 128 * i] = rnd.Next(255);
}
}
for (int i = 0; i < 20; i++)
{
points.SetNull(i);
}
for (int i = 0; i < rnd.Next(20); i++)
{
points.XValues[i] = rnd.Next(128);
points.YValues[i] = rnd.Next(128);
points.SetNull(i, false);
}
points.TreatNulls = TreatNullsStyle.Ignore;
}
Could you tell us if previous code works in correct way for you?
I hope will helps.
Thanks,

Categories