Multithreading List AddRange - c#

Issue is that TotalRows is about 71800 where the workList only returns 718 which is only the first result of the Task. I have the WaitAll there but it seems to finish as soon as the first task is done.
TotalRows = GetRowCount();
var lastRecord = 0;
List<tmpWBITEMALL> workList = new List<tmpWBITEMALL>();
for (int i = 0; i < 100; i++)
{
var tmpI = i;
gatherTmpTasks.Add(Task.Factory.StartNew(() =>
{
var context = new AS400_PIM5ContextDataContext();
context.CommandTimeout = 0;
int amount = (TotalRows / 100);
int tmplastRecord = lastRecord;
Interlocked.Add(ref lastRecord, amount);
Console.WriteLine("Getting rows " + tmplastRecord+ " to " + (tmplastRecord + amount));
var pagedResult = context.ExecuteQuery<tmpWBITEMALL>("SELECT * FROM (SELECT ROW_NUMBER() OVER ( ORDER BY Id ) AS RowNum, * from tmpWBITEMALL) AS RowConstrainedResult WHERE RowNum >= " + tmplastRecord+ " AND RowNum < " + amount + " ORDER BY RowNum");
lock (listLock)
workList.AddRange(pagedResult);
context.Dispose();
}));
}
Task.WaitAll(gatherTmpTasks.ToArray());
Console.WriteLine("total work: " + workList.Count + " tasks: " + gatherTmpTasks.Count);
So as reference gatherTmpTasks.Count returns 100 but workList.Count is only 718 where as listLock is just a static new object(). If didn't notice already I am using LINQ to SQL
Anyone have ideas why my list isn't the same size as TotalRows?

" AND RowNum < " + amount: amount is always 718, so you are asking the query to always return things between tmplastRecord and 718, NOT inbetween tmplastRecord and tmplastRecord + amount. I think you just need to change to " AND RowNum < " + (tmplastRecord + amount)
Wise man

Related

C# Multiplication Table - Only 1 multiplication is showing

I am creating a multiplication table, when you input a number and click the calculate button it should display. I have tried watching a few tutorials on YouTube and have checked out some coding forums however I can only find people using the Console Application however I am using the Windows Form Application
1 * 1 = 1
2 * 1 = 2
3 * 1 = 3
4 * 1 = 4
5 * 1 = 5
6 * 1 = 6
7 * 1 = 7
8 * 1 = 8
9 * 1 = 9
10 * 1 = 10
However, when I run the program it only displays
1 * 10 = 10
Here is my code;
private void btnCalc_Click(object sender, EventArgs e)
{
int n, i;
n = Int32.Parse(txtNum.Text);
for (i = 1; i <= 10; ++i)
txtCalc.Text = Convert.ToString(n + " * " + i + " = " + n * i);
}
This loop keeps setting the control's text to a different value over and over, leaving you to see only the final value.
for (i = 1; i <= 10; ++i)
{
txtCalc.Text = Convert.ToString(n + " * " + i + " = " + n * i);
}
A straightforward solution is:
string text = "";
for (i = 1; i <= 10; ++i)
{
text += Convert.ToString(n + " * " + i + " = " + n * i);
}
txtCalc.Text = text;
You will still run into some formatting issues you'll need to solve, but you'll get the fundamental info in there.
You're overwriting the text over and over again. What you want to do is append new text every time through the loop. Try something like:
txtCalc.Text = "";
for (i = 1; i <= 10; ++i)
{
txtCalc.Text += Convert.ToString(n + " * " + i + " = " + n * i) + Environment.NewLine;
}
your txtCalc.Text... overwrites the field in every iteration. You probably want something like this:
txtCalc.Text = "";
for (i = 1; i <= 10; ++i)
{
txtCalc.Text += Convert.ToString(n + " * " + i + " = " + n * i);
}

How to print stars depending on value of an array?

I recently make a program to calculate sum and avg of a given array. The program also want to print the histogram or stars pattern match with value of index.
Like this:
This is the code I wrote so far:
private void process_Click(object sender, EventArgs e)
{
string temp2 = null;
string temp3 = null;
float sum=0;
int countingNumber = 1;
string message;
int count = Convert.ToInt32(inputArray.Text);
int[] varray = new int[count];
for (int i = 0; i < count; i++)
//for (int j = 1; j <= count; j++)
{
varray[i] = Convert.ToInt32(Interaction.InputBox(message = "enter the value of array number " + countingNumber));
sum = sum+ varray[i];
temp += countingNumber + " "+varray[i] + Environment.NewLine;
temp2 += countingNumber + " " + varray[i] + " *" + Environment.NewLine;
box1.Text = Convert.ToString("Index Value" + Environment.NewLine + temp);
boxSum.Text = Convert.ToString(sum);
boxAvg.Text = Convert.ToString(sum/count);
countingNumber++;
}
for (int stars = 0; stars <= i; stars++)
{
temp3 = " ";
box2.Text = Convert.ToString("Element Value Histogram" + Environment.NewLine + temp2+temp3);
}
}
}
My code won't print the stars match with the value. Could anybody help me?
Try replacing this line:
temp2 += countingNumber + " " + varray[i] + " *" + Environment.NewLine;
with this line:
temp2 += countingNumber + " " + varray[i] + " " + new String('*', i) + Environment.NewLine;

how to calculate totals and minimum spanning trees using arrays

I'm working on a C# assignment in which i have to create a minimum spanning tree through the use of arrays. My code is made up of three arrays which track the nodes and whether or not they have been reached. I have to find the smallest total for all of the randomly generated links to be added up to visit all of the nodes. However, for some reason it is not quite working. The totals being produced are not correct and just wondered if anyone could help me work out why.I believe the error must be between the calculating of the total or how the minimum value is being decided or possible both however i am unsure.
So far i have tried changing the way it is calculated to involve a sum variable to store the values seperately. Ive attempted to add another if statement that would stop the min value from being anything above 98 ( the void value is 99) i have also tried to alter the earlier code to see if how i am testing the values in the SP array are the desired ones. still no results
int n = 5; //n = number of values
int m = 50; //m = max value in arra
int VoidValue = 99; // if i = j value = void value
int Total = 0; //Total value for spanning tree
int sum = 0; //Sum for total value for spanning tree
Random Rand = new Random(); //Create randomise value
int[,] c = new int[n + 1, n + 1]; //Cost array
int[] SP = new int[n + 1]; //Spanned array
int[,] AD = new int[n + 1, n + 1]; //Adjacency array
for (int i = 1; i <= n; i++)
{
SP[i] = 0;
for (int j = 1; j <= n; j++)
{
if (i == j)
{
c[i, j] = VoidValue; // give void spaces the value of 99
AD[i, j] = 0;
}
else
{
c[i, j] = Rand.Next(1, m); // Populate the array with randomised values
AD[i, j] = 0;
}
}
}
//Output all arrays to screen
Console.WriteLine("Cost Array: At the beginning");
Console.WriteLine("");
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (i == j)
{
Console.Write("c[" + i + "," + j + "] = " + "- " + " ");
}
else
{
Console.Write("c[" + i + "," + j + "] = " + c[i, j].ToString("00") + " ");
}
}
Console.WriteLine();
}
Console.ReadLine();
Console.WriteLine("");
Console.WriteLine("Spanned Array : At the beginning");
Console.WriteLine("");
for (int i = 1; i <= n; i++)
{
Console.Write("S[" + i + "] = " + SP[i].ToString("00") + " ");
Console.WriteLine();
}
Console.ReadLine();
Console.WriteLine("");
Console.WriteLine("Adjacency Array : At the beginning");
Console.WriteLine("");
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (i == j)
{
Console.Write("A[" + i + "," + j + "] = " + "- " + " ");
}
else
{
Console.Write("A[" + i + "," + j + "] = " + AD[i, j].ToString("00") + " ");
}
}
Console.WriteLine();
}
Console.ReadLine();
// Random Starting Point
int startPoint = Rand.Next(1, n + 1);
Console.WriteLine("Start at node " + startPoint);
SP[startPoint] = 1;
//Check the spanned array
Console.WriteLine("");
Console.WriteLine("Spanned Array : After the starting point has been chosen ");
Console.WriteLine("");
for (int i = 1; i <= n; i++)
{
Console.Write("S[" + i + "] = " + SP[i].ToString("00") + " ");
Console.WriteLine();
}
Console.ReadLine();
// Find minimum vallue link, repeatedly follow these links until spanned array is full
for (int p = 1; p < n; p++) // For every value of the spanned array
{
int MinValue = VoidValue, MinValuei = 0, MinValuej = 0; // declare variables
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++) // I and J are for both variables of the cost and adjacent array
if (i != j)
{
if (SP[i] == 1) //Spanned node
{
if (SP[j] == 0) //Unspanned node
{
if (c[i, j] < MinValue)
{
MinValue = c[i, j];
MinValuei = i;
MinValuej = j;
}
}
}
}
AD[MinValuei, MinValuej] = 1;
SP[MinValuej] = 1;
}
Console.WriteLine("");
Console.WriteLine("The min value is: " + MinValue);
Total = Total + MinValue;
Console.WriteLine("");
Console.WriteLine("The total is: " + Total);
}
//Finally output spanned and adjacent arrays
Console.WriteLine("");
Console.WriteLine("Spanned Array: After spanning tree");
Console.WriteLine("");
for (int i = 1; i <= n; i++)
{
Console.Write("S[" + i + "] = " + SP[i].ToString("00") + " ");
Console.WriteLine();
}
Console.ReadLine();
Console.WriteLine("");
Console.WriteLine("Adjacency Array : After spanning tree");
Console.WriteLine("");
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (i == j)
{
Console.Write("A[" + i + "," + j + "] = " + "- " + " ");
}
else
{
Console.Write("A[" + i + "," + j + "] = " + AD[i, j].ToString("00") + " ");
}
}
Console.WriteLine();
}
Console.ReadLine();
//Output total value for the spanning tree
Console.WriteLine("");
Console.WriteLine("The total value for the spanning tree: " + Total);
Console.WriteLine("");
Console.ReadLine();

Blocking Collection shows Duplicate entries

I first retrieve Total number of rows in my table (say 100) and then divide them into chunks (say 25). Then I create a task (taskFetch) which fetches rows from MyTable in chunks into DataTable (each containing 25 records) using Parallel.Foreach() method. There's another nested Parallel,Foreach() which uses Partitioner.Create() which retrieves data from each DataTable and Adds it into Blocking Collection (sourceCollection). For testing purpose I output the result on console and it was fine.
But, as I tried to retrieve data from sourceCollection I found duplicate entries. In real I have over 1500,000 records in table. I dont exactly think that duplicate entries are Add-ed but the way I'm Take-ing is something I'm a bit doubtful about.
Code
public async Task BulkMigrationAsync(string clearPVK, string EncZPK)
{
BlockingCollection<MigrationObject> sourceCollection = new BlockingCollection<MigrationObject>();
List<Task> tasksGeneratedPinBlock = new List<Task>();
int rangeFrom = 1;
int recordsInSet = 25;
int rangeTo = 25;
int setsCount = 0;
Dictionary<int, Tuple<int, int>> chunks = new Dictionary<int, Tuple<int, int>>();
SqlConnection conn = new SqlConnection(_Database.ConnectionString);
SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM MyTable); // Suppose If retrieves 100 rows
// getting total records from MyTable
using (conn)
{
conn.Open();
setsCount = Convert.ToInt32(cmd.ExecuteScalar()) / recordsInSet ; // then setsCount will be 4
conn.Close();
}
for (int i = 0; i < setsCount; i++)
{
chunks.Add(i, new Tuple<int, int>(rangeFrom, rangeTo));
rangeFrom = rangeTo + 1;
rangeTo = rangeTo + recordsInSet;
}
// Each chunk would contain 100000 records to be preocessed later
// chunks => {0, (1, 25)}
// {1, (26, 50)} // a chunk, chunk.Value.Item1 = 26 and chunk.Value.Item2 = 50
// {2, (51, 75)}
// {3, (76, 100)}
// fetching results in dataTable from DB in chunks and ADDING to sourceCollection
Task taskFetch = Task.Factory.StartNew(() =>
{
Parallel.ForEach(chunks, (chunk) =>
{
DataTable dt = new DataTable();
SqlConnection localConn = new SqlConnection(_Database.ConnectionString);
string command = #"SELECT * FROM ( SELECT RELATIONSHIP_NUM, CUST_ID, CODE, BLOCK_NEW, ROW_NUMBER() over (
order by RELATIONSHIP_NUM, CUST_ID) as RowNum FROM MyTable) SUB
WHERE SUB.RowNum BETWEEN chunk.Value.Item1 AND chunk.Value.Item2";
SqlDataAdapter da = new SqlDataAdapter(command, localConn);
try
{
using (da)
using (localConn)
{
da.Fill(dt);
}
}
finally
{
if (localConn.State != ConnectionState.Closed)
localConn.Close();
localConn.Dispose();
}
Parallel.ForEach(Partitioner.Create(0, dt.Rows.Count),
(range, state) =>
{
MigrationObject migSource = new MigrationObject();
for (int i = range.Item1; i < range.Item2; i++)
{
migSource.PAN = dt.Rows[i]["CUST_ID"].ToString();
migSource.PinOffset = dt.Rows[i]["CODE"].ToString();
migSource.PinBlockNew = dt.Rows[i]["BLOCK_NEW"].ToString();
migSource.RelationshipNum = dt.Rows[i]["RELATIONSHIP_NUM"].ToString();
Console.WriteLine(#"PAN " + migSource.PAN + " Rel " + migSource.RelationshipNum
+ " for ranges : " + range.Item1 + " TO " + range.Item2);
sourceCollection.TryAdd(migSource);
}
});
});
});
await taskFetch;
sourceCollection.CompleteAdding();
while (!sourceCollection.IsCompleted)
{
MigrationObject mig;
if (sourceCollection.TryTake(out mig)) // Seems to be the problem area because may be im not handling out
{
await Task.Delay(50);
Console.WriteLine(" Rel " + mig.RelationshipNum + " PAN " + mig.PAN);
}
}
}
My bad, Actually the problem area is :
Parallel.ForEach(Partitioner.Create(0, dt.Rows.Count),
(range, state) =>
{
MigrationObject migSource = new MigrationObject(); // creating the object outside For loop.
for (int i = range.Item1; i < range.Item2; i++)
{
migSource.PAN = dt.Rows[i]["CUST_ID"].ToString();
migSource.PinOffset = dt.Rows[i]["CODE"].ToString();
migSource.PinBlockNew = dt.Rows[i]["BLOCK_NEW"].ToString();
migSource.RelationshipNum = dt.Rows[i]["RELATIONSHIP_NUM"].ToString();
Console.WriteLine(#"PAN " + migSource.PAN + " Rel " + migSource.RelationshipNum
+ " for ranges : " + range.Item1 + " TO " + range.Item2);
sourceCollection.TryAdd(migSource);
}
});
instead I should have included ' MigrationObject migSource = new MigrationObject();' inside For loop :
Parallel.ForEach(Partitioner.Create(0, dt.Rows.Count),
(range, state) =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
MigrationObject migSource = new MigrationObject();
migSource.PAN = dt.Rows[i]["CUST_ID"].ToString();
migSource.PinOffset = dt.Rows[i]["CODE"].ToString();
migSource.PinBlockNew = dt.Rows[i]["BLOCK_NEW"].ToString();
migSource.RelationshipNum = dt.Rows[i]["RELATIONSHIP_NUM"].ToString();
Console.WriteLine(#"PAN " + migSource.PAN + " Rel " + migSource.RelationshipNum
+ " for ranges : " + range.Item1 + " TO " + range.Item2);
sourceCollection.TryAdd(migSource);
}
});

CSV file is not being written to

I am trying to write to a CSV file, and have researched a bit on how to do this and it seems pretty straightforward but it is not populating my CSV file when I run it. The program will write to a txt and my console with no issue.
StreamWriter vWriteFile = new StreamWriter("Positions2.csv");
var path = #"C:\Users\jhochbau\documents\visual studio 2015\Projects\CsvReader\CSVReader3\Position_2016_02_25.0415.csv";
if (vShowBoth == false)
{
//This determines whether to view by account or by underlying.
Console.WriteLine("Please enter 0 if you wish to see sums by account, or 12 if you wish to see by underlying");
int vViewControl = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Account" + " Settle Sum" + " Open Sum" + " Buy Sum" + " Sell Sum");
using (var parsedLines = File.ReadLines(path).Select(line => line.Split(',')).GetEnumerator())
{
bool vMore = parsedLines.MoveNext();
while (vMore)
{
// Initialize
bool vWasSuccessful;
var vAccount = parsedLines.Current[vViewControl];
double vSettleMMSum = 0;
double vOpenSum = 0;
int vBuySum = 0;
int vSellSum = 0;
do
{
double vParseSettleMM = 0;
double vParseOpen = 0;
int vParseBuy = 0;
int vParseSell = 0;
//Parsing data read in from strings, into temp variables
vWasSuccessful = double.TryParse(parsedLines.Current[7], out vParseSettleMM);
vWasSuccessful = double.TryParse(parsedLines.Current[8], out vParseOpen);
vWasSuccessful = int.TryParse(parsedLines.Current[6], out vParseBuy);
vWasSuccessful = int.TryParse(parsedLines.Current[10], out vParseSell);
//adding temp variabels to sum
vSettleMMSum += vParseSettleMM;
vOpenSum += vParseOpen;
vBuySum += vParseBuy;
vSellSum += vParseSell;
vMore = parsedLines.MoveNext();
}
//sets up when to break
while (vMore && vAccount == parsedLines.Current[vViewControl]);
//After each Break need to print out Account name and sums from above.
// Do printing here as part of the loop, at the very end of the loop code block.
Console.WriteLine("--------------------------------------------------------");
Console.WriteLine(vAccount + " " + vSettleMMSum + " " + vOpenSum + " " + vBuySum + " " +
vSellSum);
//vWriteFile.Write(vAccount + "," + vSettleMMSum + "," + vOpenSum + "," + vBuySum + "," +
// vSellSum);
vWriteFile.WriteLine("{0},{1},{2},{3},{4}", vAccount, vSettleMMSum, vOpenSum, vBuySum, vSellSum);
//reset sums for next loop
vSettleMMSum = 0;
vOpenSum = 0;
vBuySum = 0;
vSellSum = 0;
}
}
}
You should make it a habit to wrap your streams with the using keyword so you don't run into situations where you forget to close it out. It's a good practice to use the using keyword around anything that inherits IDisposable
So your code would look like this.
using(StreamWriter vWriteFile = new StreamWriter("Positions2.csv"))
{
var path = #"C:\Users\jhochbau\documents\visual studio 2015\Projects\CsvReader\CSVReader3\Position_2016_02_25.0415.csv";
if (vShowBoth == false)
{
//This determines whether to view by account or by underlying.
Console.WriteLine("Please enter 0 if you wish to see sums by account, or 12 if you wish to see by underlying");
int vViewControl = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Account" + " Settle Sum" + " Open Sum" + " Buy Sum" + " Sell Sum");
using (var parsedLines = File.ReadLines(path).Select(line => line.Split(',')).GetEnumerator())
{
bool vMore = parsedLines.MoveNext();
while (vMore)
{
// Initialize
bool vWasSuccessful;
var vAccount = parsedLines.Current[vViewControl];
double vSettleMMSum = 0;
double vOpenSum = 0;
int vBuySum = 0;
int vSellSum = 0;
do
{
double vParseSettleMM = 0;
double vParseOpen = 0;
int vParseBuy = 0;
int vParseSell = 0;
//Parsing data read in from strings, into temp variables
vWasSuccessful = double.TryParse(parsedLines.Current[7], out vParseSettleMM);
vWasSuccessful = double.TryParse(parsedLines.Current[8], out vParseOpen);
vWasSuccessful = int.TryParse(parsedLines.Current[6], out vParseBuy);
vWasSuccessful = int.TryParse(parsedLines.Current[10], out vParseSell);
//adding temp variabels to sum
vSettleMMSum += vParseSettleMM;
vOpenSum += vParseOpen;
vBuySum += vParseBuy;
vSellSum += vParseSell;
vMore = parsedLines.MoveNext();
}
//sets up when to break
while (vMore && vAccount == parsedLines.Current[vViewControl]);
//After each Break need to print out Account name and sums from above.
// Do printing here as part of the loop, at the very end of the loop code block.
Console.WriteLine("--------------------------------------------------------");
Console.WriteLine(vAccount + " " + vSettleMMSum + " " + vOpenSum + " " + vBuySum + " " +
vSellSum);
//vWriteFile.Write(vAccount + "," + vSettleMMSum + "," + vOpenSum + "," + vBuySum + "," +
// vSellSum);
vWriteFile.WriteLine("{0},{1},{2},{3},{4}", vAccount, vSettleMMSum, vOpenSum, vBuySum, vSellSum);
//reset sums for next loop
vSettleMMSum = 0;
vOpenSum = 0;
vBuySum = 0;
vSellSum = 0;
}
}
}
}

Categories