Multi threading not executing properly - c#

I have a function here that calls another function in multiple threads. In the second functions, the value of each element of refValuesd[,] is 1. But when I check the elements of the same 2D array in the graph1() function after the multiple threads are called, I get different values for the elements of refValuesd[,].I am a novice in multithreading.
void graph1()
{
for (int j = 0; j < 366; j++) //loop to refresh element values
{
refValues[j] = 0;
threshValues[j] = 0;
y_Values[j] = 0;
y__Values[j] = 0;
yValues[j] = 0;
for (int k = 0; k < 1000; k++)
{
threshValuesd[k,j] = 0;
refValuesd[k,j] = 0;
y__Valuesd[ k,j] = 0;
y_Valuesd[k,j] = 0;
yValuesd[k,j] = 0;
}
}
List<string>[] list = new List<string>[4];//manpower details
list = A.mandetselect();
int number = A.Countmandet();//retuns an integer value
string[] trade = list[1].ToArray();
string[] license = list[2].ToArray();
string[] training = list[3].ToArray();
string[] display_status = list[4].ToArray();
List<string>[] listc = new List<string>[14];//Project details
listc = A.Select();
int numberc = A.Count();
string abc = "";
int q = 0;
for (int j = 0; j < number; j++)
{
if (!display_status[j].Equals("NO") && (selection == "ALL" || (selection == "ALL-LAE" && license[j] != "") || (selection == "ALL-NON LAE" && license[j] == "") || (selection == "AVIONICS -ALL" && trade[j] == "Avionics") || (selection == "AVIONICS-NON LAE" && trade[j] == "Avionics" && license[j] == "") || (selection == "AVIONICS-LAE" && trade[j] == "Avionics" && license[j] != "") || (selection == "AIRFRAME-ALL" && trade[j] == "Airframes") || (selection == "AIRFRAME-NON LAE" && trade[j] == "Airframes" && license[j] == "") || (selection == "AIRFRAME-LAE" && trade[j] == "Airframes" && license[j] != "")))
{
int z = numberc;
string[] nameofproj = listc[0].ToArray();
int copy = q;
int copy2 = j;
string a = abc;
string[] name = list[0].ToArray();
List<string>[] lista = new List<string>[5];
string[] status = listc[13].ToArray();
thread[copy] = new Thread(() => graph1threader(a, name[copy2], lista, z, nameofproj, status, copy));
thread[copy].Start();
q++;
}
}
for (int j = 0; j < 366; j++)
{
for (int k = 0; k < q; k++)
{
threshValues[j] += threshValuesd[k, j];
refValues[j] += refValuesd[k, j];
y__Values[j] += y__Valuesd[k, j];
y_Values[j] += y_Valuesd[k, j];
yValues[j] += yValuesd[k, j];
}
}
for (int j = 0; j < 366; j++)
{
DateTime temp = G.AddDays(j);
string temper = temp.ToShortDateString();
y__Values[j] = y__Values[j] - y_Values[j];
xNames[j] = temper;
}
chart1.Series[1].Points.DataBindXY(xNames, y_Values);
chart1.Series[2].Points.DataBindXY(xNames, y__Values);
chart1.Series[3].Points.DataBindXY(xNames, refValues);
chart1.Series[4].Points.DataBindXY(xNames, threshValues);
chart1.Series[5].Points.DataBindXY(xNames, yValues);
}
Here is the function that is executed on multiple threads:
void graph1threader(string abc,string nameofj,List<string>[] lista,int numberc,string[] nameofproj,string[] status,int copy )
{
DBConnect A = new DBConnect();
int x = copy;
string[] projname;
string[] country;
string[] start;
string[] end;
abc = nameofj.Replace(" ", "_");
lista = A.manprojselect(abc);
projname = lista[0].ToArray();
country = lista[2].ToArray();
start = lista[3].ToArray();
end = lista[4].ToArray();
for (int k = 0; k < 366; k++)//basic
{
refValuesd[x, k]++;
refValuesd[copy,k].ToString());
threshValuesd[x, k] = 0.8;
string Status = "";
int flag = 0;
for (int l = 0; l < A.Countproj(abc); l++)
{
for (int m = 0; m < numberc; m++)
{
if (nameofproj[m] == projname[l])
{
Status = status[m];
}
}
DateTime shuru = DateTime.ParseExact(start[l],
"dd-MM-yyyy hh:mm:ss",
CultureInfo.InvariantCulture);
DateTime anth = DateTime.ParseExact(end[l],
"dd-MM-yyyy hh:mm:ss",
CultureInfo.InvariantCulture);
if (temp >= shuru && temp <= anth)
{
if (Status != "PLANNED" && Status != "LO" && flag == 0)
{
y_Valuesd[x,k]++;//BASIC UTILISATION
flag = 1;
}
if (Status == "IP" || Status == "OTD")
y__Valuesd[x,k]++;//EXCESS
if (Status == "PLANNED")
{
yValuesd[x,k]++;//UNUTILISED
}
}
}
}
}

There's probably a few problems in there, but two I can spot:
Firstly, the threads are trying to do refValuesd[x, k]++ which isn't threadsafe.
Try this instead:
Interlocked.Increment(ref refValuesd[x, k]);
Secondly, you are not waiting for all the threads to terminate before using the data they've generated. Try adding this just before the for (int j = 0; j < 366; j++) line:
foreach (var thread in threads)
thread.Join();
It looks like you have much to learn, so I recommend that you read this free ebook:
http://www.albahari.com/threading/

Make sure you surround access to refvalued with lock sections and you will start in the right direction. You have to design your locking not to create race conditions and deadlocks as well.
EDIT: So, having reviewed your code, here are a few comments
It looks like you kick off the graph function, which in turn executes the graph1threader function on multiple threads. I won't question whether or not that is necessary - the assumption is that you've already decided it is.
Order of events
It looks like you don't stop to wait for all the graph1threader threads to complete before continuing in your second loop. So here is a question:
Do you want the graph1threader jobs to complete before you continue?
If so, have you looked at Task? Instead of creating threads, you could almost literally swap Thread with Task and then, once you have completed the creation of all your Task objects and started them, you could put Task.WaitAll after your for (int j = 0; j < number; j++) loop to wait for them to complete before you then do the third for loop in graph1:
thread[copy] = new Task(() => graph1threader(a, name[copy2], lista, z, nameofproj, status, copy));
thread[copy].Start();
q++;
}
}
Task.WaitAll(thread);
for (int j = 0; j < 366; j++)
{
for (int k = 0; k < q; k++)
{
threshValues[j] += threshValuesd[k, j];
refValues[j] += refValuesd[k, j];
y__Values[j] += y__Valuesd[k, j];
y_Values[j] += y_Valuesd[k, j];
yValues[j] += yValuesd[k, j];
}
}
If you don't want to use Task (or can't) Thread.Join will also work, but Task supports cancellation easier than Thread so if you have a UI with long running operations it will make things easier for you.
Shared fields
The following variables are used by both functions (please ignore any incorrect variables types, it is the names that are important):
double[,] threshValuesd;
int[,] refValuesd;
int[,] y__Valuesd;
int[,] y_Valuesd;
int[,] yValuesd;
I am calling this list bookmark A to be used later
All these potentially need protecting against multi-threaded race conditions etc.
How to protect the shared fields
Regardless of whether you wait or not, you need to protect your shared fields in graph1threader. So, if I've read your code properly:
you pass a unique, incremented value to graph1threader (using q++ in your 2nd for loop in graph1)
Therefore the following lines will not compete to set values between threads in graph1threader:
refValuesd[x, k]++;
threshValuesd[x, k] = 0.8;
y_Valuesd[x,k]++;
y__Valuesd[x,k]++;
yValuesd[x,k]++;
(Side note: these variable names are incomprehensible to me, you might try naming them in a more descriptive way than yValuesd, y_Valuesd and y__Valuesd to help you debug this later).
However, even if threads don't compete to update values in the same array slot, you probably have problems coming in the form of memory barriers and read/write access to a single array slot. Therefore, I would recommend doing this, quite simply declare a class field:
private readonly object SyncRoot = new object();
and then around all access to any of the shared fields I mentioned above bookmark A you need to use (picking your first loop as an example):
lock (this.SyncRoot) {
for (int j = 0; j < 366; j++)
{
for (int k = 0; k < q; k++)
{
threshValues[j] += threshValuesd[k, j];
refValues[j] += refValuesd[k, j];
y__Values[j] += y__Valuesd[k, j];
y_Values[j] += y_Valuesd[k, j];
yValues[j] += yValuesd[k, j];
}
}
}
Keep lock calls as infrequent as possible, but as close to the shared resource as possible. By that I mean that you could lock inside the inner for loop if you wanted to, but that will be slower, however you may need that to allow other threads to proceed more frequently if they also lock the same object.
NOTE: This technique of using a shared lock assumed you wanted the graph1threader threads to be running at the same time as your third for loop in graph1 (i.e. my comment about Task objects wasn't required). If this is not the case, I think you could create a local object within each function and lock on that instead. Each thread would therefore have a different lock object. Because no thread accesses the same slot in your arrays at the same time, this would just enforce memory barriers and ensure that all threads saw the same values when they read them.
Sorry this was so long, it was hard to know where to start without know more about the assumptions you went through to build this code.

Related

Code seems to move on prior to Parallel.For loops finishing

I'm struggling with using Parallel.For loops. I can tell they really speed up my long running code but I'm get null object errors as though the code moved on prior to completing the parallel loops. Below is my code with commented out Parallel.For statements that I've tried.
public bool Calculate()
{
// make list of all possible flops 22100
List<Flop> flops = new List<Flop>();
CardSet deck = new CardSet();
for (int i = 0; i < deck.Size() - 2; i++)
{
SbCard card1 = deck.GetCard(i);
for (int j = i + 1; j < deck.Size() - 1; j++)
{
SbCard card2 = deck.GetCard(j);
for (int k = j + 1; k < deck.Size(); k++)
{
SbCard card3 = deck.GetCard(k);
flops.Add(new Flop(card1, card2, card3));
}
}
}
int progress = 0;
var watch = System.Diagnostics.Stopwatch.StartNew();
// Loop over each flop
//Parallel.For(0, flops.Count, i =>
for (int i = 0; i < flops.Count; i++)
{
Dictionary<FlopEquityHoldemHandPair, FlopEquityHoldemHandPair> flopPairs =
new Dictionary<FlopEquityHoldemHandPair, FlopEquityHoldemHandPair>();
Flop flop = flops[i];
String filePath = Directory.GetCurrentDirectory() + "\\flops\\" +
flop.GetSorted() + ".txt";
if (!File.Exists(filePath))
{
// make list of all available starting hands
List<HoldemHand> hands = new List<HoldemHand>();
deck = new CardSet();
deck.RemoveAll(flop);
for (int j = 0; j < deck.Size() - 1; j++)
{
SbCard card1 = deck.GetCard(j);
for (int k = j + 1; k < deck.Size(); k++)
{
SbCard card2 = deck.GetCard(k);
hands.Add(new HoldemHand(card1, card2));
}
}
// loop over all hand vs hand combos
//Parallel.For(0, hands.Count - 1, j =>
for (int j = 0; j < hands.Count - 1; j++)
{
HoldemHand hand1 = hands[j];
//Parallel.For(j + 1, hands.Count, k =>
for (int k = j + 1; k < hands.Count; k++)
{
HoldemHand hand2 = hands[k];
if (!hand1.Contains(hand2))
{
FlopEquityHoldemHandPair holdemHandPair = new
FlopEquityHoldemHandPair(hand1, hand2);
if (!flopPairs.ContainsKey(holdemHandPair))
{
// next line triggers a loop of 1980 iterations
flopPairs.Add(holdemHandPair, new
FlopEquityHoldemHandPair(new
EquityHoldemHand(hand1), new
EquityHoldemHand(hand2), flop));
}
}
}//);
}//);
// WRITE FILE FOR CURRENT FLOP
StringBuilder sb = new StringBuilder();
foreach (FlopEquityHoldemHandPair pair in flopPairs.Values)
{
// Null value appears in flopPairs.Values and the list of values is around 200 short of the 600k values it should have
sb.AppendLine(pair.ToString());
}
File.WriteAllText(filePath, sb.ToString());
// reports calculation progress 1% at a time
int num = ((int)(i * 100 / 22100));
if (num > progress)
{
progress = num;
Console.WriteLine("Progress: " + progress + "%");
}
}
}//);
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine("Finished in " + elapsedMs / 60000 + "mins");
return true;
}
When I arrive at the foreach loop late in this code, some items in flopPairs. Values are null and the dictionary is not quite as big as it should be - as though some calculations did not finish before the code moved on. I apologize that this code is not runnable without more code but there is a lot to provide. I can attempt to provide a minimal simplified example that runs if the problem is not fairly obvious to somebody.
As John Wu stated in the comments, Dictionary is not thread safe and was causing my problems. Using ConcurrentDictionary was the correct answer

Does writing if statements differently affect the speed and efficiency of the program?

I an curious if writing if statements differently can affect the speed and efficiency of a program. So, for example writing one like this:
bool isActive = true;
bool isResponding = false;
if (isActive && isResponding)
{
//do this
}
is it more optimal than:
if (isActive)
{
if (isResponding)
{
// do this
}
}
or is it vice versa or is there no difference at all? The reason i am asking about this if statement is because of the AND && and the amount of asm functions it creates after compilation. Or how about:
if (isActive || isResponding)
{
//do this
}
is this more optimal than:
if (isActive)
{
//do this #1
}
else if (isResponding)
{
//do this #1
}
//do this #2
Just like with the AND &&, i am curious because of the OR ||
No, it does not affect performance, because && and || are so called "short-circuit operators", that is, statements they are linking will not be fired if there is no point in doing that.
For example
if( true && myBoolFunc() ) - myBoolFunc will fire because after checking true we still don't know if whole statement is true.
if( false && myBoolFunc() ) - myBoolFunc will NOT fire because after checking false we already know, that whole statement is false.
if( true || myBoolFunc() ) - myBoolFunc will NOT fire because after checking true we already know, that whole statement is true.
if( false || myBoolFunc() ) - myBoolFunc will fire because after checking false still don't know if whole statement is false.
And if you want some more details about how does it work, just read this Wikipedia article
I've measured just for curiosity, and the results did not say there is a difference.
Test code:
private static void testIfs()
{
int count = 100000;
{
Stopwatch w = Stopwatch.StartNew();
int test = 0;
bool isActive = true;
bool isResponding = false;
for (int j = 0; j < count; j++)
for (int i = 0; i < count; i++)
if (isActive && isResponding)
test++;
test = 0;
isActive = false;
isResponding = true;
for (int j = 0; j < count; j++)
for (int i = 0; i < count; i++)
if (isActive && isResponding)
test++;
w.Stop();
Console.WriteLine("using &&: " + w.ElapsedTicks);
}
{
Stopwatch w = Stopwatch.StartNew();
int test = 0;
bool isActive = true;
bool isResponding = false;
for (int j = 0; j < count; j++)
for (int i = 0; i < count; i++)
if (isActive)
if (isResponding)
test++;
test = 0;
isActive = false;
isResponding = true;
for (int j = 0; j < count; j++)
for (int i = 0; i < count; i++)
if (isActive)
if (isResponding)
test++;
w.Stop();
Console.WriteLine("using 2 ifs: " + w.ElapsedTicks);
}
{
Stopwatch w = Stopwatch.StartNew();
int test = 0;
bool isActive = true;
bool isResponding = false;
for (int j = 0; j < count; j++)
for (int i = 0; i < count; i++)
if (isActive || isResponding)
test++;
test = 0;
isActive = false;
isResponding = true;
for (int j = 0; j < count; j++)
for (int i = 0; i < count; i++)
if (isActive || isResponding)
test++;
w.Stop();
Console.WriteLine("using ||: " + w.ElapsedTicks);
}
{
Stopwatch w = Stopwatch.StartNew();
int test = 0;
bool isActive = true;
bool isResponding = false;
for (int j = 0; j < count; j++)
for (int i = 0; i < count; i++)
if (isActive)
test++;
else if (isResponding)
test++;
test = 0;
isActive = false;
isResponding = true;
for (int j = 0; j < count; j++)
for (int i = 0; i < count; i++)
if (isActive)
test++;
else if (isResponding)
test++;
w.Stop();
Console.WriteLine("using else if: " + w.ElapsedTicks);
}
}
Some tries (Release build with optimize code enabled):
using &&: 21449771
using 2 ifs: 20845600
using ||: 21025834
using else if: 21018318
using &&: 21041437
using 2 ifs: 21899080
using ||: 20442059
using else if: 21345493
using &&: 20629055
using 2 ifs: 20135598
using ||: 20407510
using else if: 20264467
using &&: 20152862
using 2 ifs: 19676131
using ||: 19910502
using else if: 19918131
Has no effect for the scenarios what you are suggesting. The compiler automatically takes care of it and performs plenty of optimizations.
But even compilers have limitations. It won't know what values will be often assigned to the variables. As a developer, you would know that.
In your example:
bool isActive = <RETVAL_OF_SOME_FUNCTION>;
bool isResponding = <RETVAL_OF_SOME_FUNCTION>;
if (isActive && isResponding)
{
//do this
}
Its quite obvious that we needn't bother with isResponding if isActive is false. Hence isActive should be present first in the sequence of statements in the AND condition. This will ensure that while running it'll not waste processing power to check for isResponding when isActive would be false.(just a sample example as isResponding would be false anyway if isActive is false)
While this is a very small optimization, it will not be done by the compiler. The compiler will have no idea what the variables represents. It'll just look for pre-programmed optimizations and implement it.
In this cascade of AND or OR the controlling condition should always come first.
There can be 2 possible scenarios for degradation of performance:
Too much data fetch
Too much fetch operation will drastically slow down your working. Typical fetch from RAM takes 200-300 processor cycles. Loading from L1 cache takes barely 1-3 cycles. Load too much data can/will also cause page faults, leading to loading from HDD storage, which is even slower. The processor will wait idly by during the load process
Poorly structured code
Don't use structures where some elements will be empty. An Excel cell is an example of that. Each cell has so many fields that copying one cell will copy a lot of info. I guess they may have implemented an optimized logic (dunno), but avoid using large data structures. It'll increase overheads during threading as well as when passing as function arguments.
Their effects may look negligible, but will add up in the long run if you are going to run it repeatedly in a system.
You don't need to bother with optimizations if the code will run less than 1000 times per day(depends on code execution time). The above optimizations I've talked about were actually implemented logic that speed up the code execution by about 60% in a system that runs continuously every 1us.
actually the difference between the statement is the number of basic instructions in this example:
if (isActive && isResponding){
//do this}
here the cpu will calculate isActive and isResponding than check the result if it's 0 or 1
otherwise in the other code he'll do 2 checks the difference in terms of performance will spear if the if statemented is repeated in a huge among of times
i hope i could helped

indexOutofRange BubbleSort when using inputbox

Its been bugging me for hours because it is always returning 0 at numbers[i] and I cant figure out the problem. code worked for a different program but I had to change it so it could have a custom array size and that's when everything went wrong.
any help would be great.
Thanks in advance.
int[] numbers = new int[Convert.ToInt16(TxtArray.Text)];
int j = 0;
for (j = numbers.Length; j >= 0; j--)
{
int i = 0;
for (i = 0; i <= j - 1; i++)
{
string NumbersInput = Microsoft.VisualBasic.Interaction.InputBox("Enter Numbers to be sorted",
"Numbers Input", "", -1, -1);
numbers[i] = Convert.ToInt16(NumbersInput);
//returns 0 in if statement
if (numbers[i] < numbers[i + 1])
{
int intTemp = 0;
intTemp = numbers[i];
numbers[i] = numbers[i + 1];
numbers[i + 1] = intTemp;
}
}
}
for (int i = 0; i < numbers.Length; i++)
{
LstNumbers.Items.Add(numbers[i]);
}
private void button1_Click(object sender, EventArgs e)
{
int sizeOfArrayInt = Convert.ToInt32(arraySize.Text);
int[] array = new int[sizeOfArrayInt];
string numbers = arrayValues.Text;
string[] numbersSplit = numbers.Split(',');
int count = 0;
foreach (string character in numbersSplit)
{
int value;
bool parse = Int32.TryParse(character, out value);
if (value != null)
{
array[count] = value;
}
count++;
}
array = this.SortArray(array);
foreach (int item in array)
{
this.listBox.Items.Add(item);
}
}
private int[] SortArray(int[] arrayToSort)
{
//int[] sortedArray = new int[arrayToSort.Length];
int count = arrayToSort.Length;
for (int j = count; j >= 0; j--)
{
int i = 0;
for (i = 0; i <= j - 2; i++)
{
if (arrayToSort[i] < arrayToSort[i + 1])
{
int intTemp = 0;
intTemp = arrayToSort[i];
arrayToSort[i] = arrayToSort[i + 1];
arrayToSort[i + 1] = intTemp;
}
}
}
return arrayToSort;
}
strong text
This I got to work as a Windows Form and the output displays in the list box as each array item or individual i iteration over the array. Of course there is no error checking. Hope that helps.
Setting aside the strangeness of how you are working with text boxes, your problem with throwing an exception would happen even without them because it lies here, in your inner loop:
for (i = 0; i <= j - 1; i++)
Suppose that numbers.Length == 2. This means that j == 2. So on the first time through the outer loop, you hit the inner loop with these conditions. The first time through, i == 0. You get to the if statement:
if (numbers[i] < numbers[i + 1])
numbers[0] exists, and numbers[1] exists, so this iteration goes through fine and i is incremented.
Now i == 1. Now the loop checks its boundary condition. i <= j - 1 == true, so the loop continues. Now when you hit that if statement, it tries to access numbers[i + 1], i.e., numbers[2], which does not exist, throwing an IndexOutOfRangeException.
Edit: Came back and realized that I left out the solution (to the exception, anyway). For the bubble sort to work, your inner loop's boundary condition should be i <= j - 2, because j's initial value is == numbers.Length, which is not zero-based, while array indexes are.
Second Edit: Note that just using a List won't actually solve this problem. You have to use the right boundary condition. Trying to access list[list.Count()] will throw an ArgumentOutOfRangeException. Just because a List will dynamically resize doesn't mean that it will somehow let you access items that don't exist. You should always take time to check your boundary conditions, no matter what data structure you use.

Need 'System.IndexOutOfRangeException' solution

if (Int32.Parse(strTotals) == 0 && nTotalCount != 0)
{
nTotalCount = 0;
for (int j = 0; j < 66; j++)
{
if (GameHistoryPicBox1[j].InvokeRequired)
{
GameHistoryPicBox1[j].BeginInvoke(new MethodInvoker(() =>
{
if ((j + j / 6) % 2 == 0)
GameHistoryPicBox1[j].Image = Properties.Resources.al1; // Line2
else
GameHistoryPicBox1[j].Image = Properties.Resources.al2; // Line4
}));
}
else
{
if ((j + j / 6) % 2 == 0)
GameHistoryPicBox1[j].Image = Properties.Resources.al1;
else
GameHistoryPicBox1[j].Image = Properties.Resources.al2;
}
}
}
I have been checking nTotalCount value by using thread.
If nTotalCount is zero, then I must clean all game picture box image.
So I was implement above code.
Unfortunately, I got the error:
An unhandled exception of type 'System.IndexOutOfRangeException'
on Line 2 and 4.
And the j value was 66.
Is it possible that j value could be 66?
This is because of how closures work. Your lambda expression that you're creating and passing to the MethodInvoker references the j variable by reference. Thus when this piece of code is being executed (which can be almost any time, as it's asynchronous) the j variable can have any value from 0 to 66. And it can be 66 after the loop has finished.
A quick fix is to make a copy of j:
int index = j;
GameHistoryPicBox1[index].BeginInvoke(new MethodInvoker(() =>
{
if ((index + index / 6) % 2 == 0)
GameHistoryPicBox1[index].Image = Properties.Resources.al1; // Line2
else
GameHistoryPicBox1[index].Image = Properties.Resources.al2; // Line4
}));
You can read more about this here.
The variable j is being passed into the closure, and because the call is asynchronous, it is actually executed at some point after the loop completes. You cannot be sure what the value of j will be when the delegate is executed.
Try passing the value of j in as a parameter to the delegate, like this:
GameHistoryPicBox1[j].BeginInvoke(new Action<int>((x) =>
{
if ((x + x / 6) % 2 == 0)
GameHistoryPicBox1[x].Image = Properties.Resources.al1;
else
GameHistoryPicBox1[x].Image = Properties.Resources.al2;
}), j);
You've been bitten by the loop-variable-in-a-closure-bug.
Instead of
for (int j = 0; j < 66; j++)
{
//blahblahblah
}
write
for (int jj = 0; jj < 66; jj++)
{
int j = jj;
//blahblahblah
}

Many else and if statements?

I am reading a csv file which has column names in first line and values in line >1. I need to get the position of the column name. The only way I can think of is to do either switch or ifs. I read it somewhere that in my case , it is faster (better) to do the ifs. However the file has many columns (~120). Just wondering if there is an alternative(s).
private static void Get_Position(string line, performance p)
{
string[] line_split = line.Split(',');
for (int i = 0; i < line_split.Length; i++)
{
if (line_split[i].Contains(#"(0)\% Processor Time"))
{
p.percore[0] = i;
}
else if (line_split[i].Contains(#"(1)\% Processor Time"))
{
p.percore[1] = i;
}
else if (line_split[i].Contains("Private Bytes"))
{}
else if (line_split[i].contains("DPC")
{
}
//on and on and on with else ifs
What is preventing you from using a loop?
for (int i = 0; i < line_split.Length; i++)
{
for(var j = 0; j < 120; j++)
{
if(line_split[i].Contains(#"(" + j + ")\% Processor Time"))
{
p.percore[j] = i;
}
}
...
To maintain the same functionality as if else if then you could use a break inside the conditional.
Edit: The edit now made it clear that there is no clear pattern to the string in contains. Still, if you are writing out 120 if/else if statements you should store what you will be looking for in some type of collection. For example, a List would work. Then access the index j of the collection in your loop:
...
var listOfSearchItems = new List<string>() { "Private Bytes", "DPC" };
for (int i = 0; i < line_split.Length; i++)
{
for(var j = 0; j < 120; j++)
{
if(line_split[i].Contains(listOfSearchItems[j])
{
p.percore[j] = i;
}
}
...

Categories

Resources