Having trouble with creating arrays in a for loop and scoping - c#

I have to assign values to members(I don't know if this is the right term) of an array. I delcared my array members as follow: (all this code is inside a public class BWClass)
public static BackgroundWorker[] bwCA = new BackgroundWorker[25];
public static int NumbwCA;
private static bool HasRunOnce = false;
public static void BackgroundWorkerInitializer(bool doFirst, int numbwCA)
{
// Okay we got here. So we can presume that array checking (number not exceeding the array) is already done
if (!HasRunOnce)
{
NumbwCA = numbwCA; // for access
} // Now it is impossible to stop less backgroundworkers then started later on in the code
if (doFirst)
{
for (int i = 0; i < NumbwCA; i++)
{
string strpara = (numbwCA.ToString()); // Could also directly write numbwCA.ToString() directly in the RunWorkerAsync() method
bwCA = new BackgroundWorker[NumbwCA];
bwCA[i] = new BackgroundWorker();
bwCA[i].WorkerReportsProgress = true;
bwCA[i].WorkerSupportsCancellation = true;
bwCA[i].DoWork += new DoWorkEventHandler(bwa_DoWork);
bwCA[i].ProgressChanged += new ProgressChangedEventHandler(bwa_ProgressChanged);
bwCA[i].RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwa_RunWorkerCompleted);
bwCA[i].RunWorkerAsync(strpara);
}
}
else // DoSecond
{
// stop the backgroundworkers
for (int i = 0; i < NumbwCA; i++)
{
if (bwCA[i].IsBusy == true)
{
bwCA[i].CancelAsync();
HasRunOnce = false; // If restarting the server is required. The user won't have to restart the progrem then
}
else
{
Console.WriteLine(">>The backgroundworkers are already finished and don't need canceling");
}
}
}
}
Al this code is inside a public class.
I thought that when I do all the array making in a class I won't have the problem of variable scopes anymore. But I was wrong. I still get the Error nullReferenceException when the bwCA[i].IsBusy == true runs. Probably also when anything outside the for loop runs.
I know that I can't use the bwCA[i] outside the loop were it is declared but how do I change this, so that I can access bwCA[i] (anywhere) else in the code (like in the "else // DoSecond)?
btw. I prefer not to use a List

You need to move the array creation outside the loop
// here for instance
bwCA = new BackgroundWorker[NumbwCA];
if (doFirst)
{
for (int i = 0; i < NumbwCA; i++)
{
string strpara = (numbwCA.ToString());
// bwCA = new BackgroundWorker[NumbwCA];
That still leaves a few issues with cleanup and running this Initializer twice.
More general, try to avoid static stuff and you shouldn't be needing 25 Backgroundworkers in the first place.
Tasks are probably more appropriate but we can't tell.

Related

i'm trying to make queue class by c # the why dequeueing function doesn't work?

this is the class
data members and getters and setters:
class Queue
{
int[] data; //array
int size; //size of array
int counter; //checker if array is fully or impty
int first; // first element of array
int last; // last element of arry
}
fixed size constructor
public Queue(int size) {
data = new int[this.size];
size = this.size;
counter = 0;
first = 0;
last = 0;
}
default constructor
public Queue() { //default constructor
data = new int[10];
size = 10;
counter = 0;
first = 0;
last = 0;
}
enqueing function "push"
public bool Enqueue(int num) {
bool result;
if (counter<size)
{
data[last] = num;
last++;
if(last == size)
last = 0;
counter++;
return result = true
}
else
{
return result = false;
}
return result;
}
dequeueing function "pop"
public int Dequeueing() {
int result=-1;
// I know that i should make this nullable function but (-1) good at this time
if (counter>0)
{
result = data[first];
first++;
if (first==size)
first = 0;
counter--;
}
return result;
}
on the main it is excute the enqueueing good but dequeueing its (first++)and (counter--) but it doesn't delete first input **
**why it doesn't delete (17)
static void Main(string[] args)
{
Queue q1 = new Queue();
q1.Enqueue(17);
q1.Enqueue(20);
q1.Enqueue(25);
q1.Enqueue(15);
q1.Enqueue(14);
q1.Enqueue(13);
q1.Dequeueing();
Console.ReadLine();
}
Your expectation that once you do first++; and counter--;, the data[first] will be deleted is misplaced. Frankly, if it will somehow cause data[first] to be deleted then rest of your code will not work. What that code does is to simply Dequeue. The Queue bounds are marked using first and last, with the help of counter, so only those things need to change and no array element deletion needs to happen
Let me help you understand your code a bit. Your Queue class is what is called a Circular Queue. In such an implementation, you have the benefit that the amount of storage allocated for the Queue is "fixed" and determined on construction. This also implies that when you Enqueue there will be no extra memory requested and when you Dequeue there will be no memory released.
If you wish to somehow identify an unoccupied slot in the array, you can use special values. For example, making int?[] data, you can store var item = data[front]; data[front] = null before Dequeueing. Or, you can use a routine like GetQueueData to return all the elements in the Queue as a separate IEnumerable
public IEnumerable<int> GetQueueData() {
for (int i = first, cnt = 0; cnt < counter; i = (i + 1) % size, ++cnt)
yield return data[i];
}
The array named data will remain in the same state as when you created it as you have not done anything to make this otherwise.

Why is the regular multiplication operator is much more efficient than the BigMul method?

I've searched for the differences between the * operator and the Math.BigMul method, and found nothing. So I've decided I would try and test their efficiency against each other. Consider the following code :
public class Program
{
static void Main()
{
Stopwatch MulOperatorWatch = new Stopwatch();
Stopwatch MulMethodWatch = new Stopwatch();
MulOperatorWatch.Start();
// Creates a new MulOperatorClass to perform the start method 100 times.
for (int i = 0; i < 100; i++)
{
MulOperatorClass mOperator = new MulOperatorClass();
mOperator.start();
}
MulOperatorWatch.Stop();
MulMethodWatch.Start();
for (int i = 0; i < 100; i++)
{
MulMethodClass mMethod = new MulMethodClass();
mMethod.start();
}
MulMethodWatch.Stop();
Console.WriteLine("Operator = " + MulOperatorWatch.ElapsedMilliseconds.ToString());
Console.WriteLine("Method = " + MulMethodWatch.ElapsedMilliseconds.ToString());
Console.ReadLine();
}
public class MulOperatorClass
{
public void start()
{
List<long> MulOperatorList = new List<long>();
for (int i = 0; i < 15000000; i++)
{
MulOperatorList.Add(i * i);
}
}
}
public class MulMethodClass
{
public void start()
{
List<long> MulMethodList = new List<long>();
for (int i = 0; i < 15000000; i++)
{
MulMethodList.Add(Math.BigMul(i,i));
}
}
}
}
To sum it up : I've created two classes - MulMethodClass and MulOperatorClass that performs both the start method, which fills a varible of type List<long with the values of i multiply by i many times. The only difference between these methods are the use of the * operator in the operator class, and the use of the Math.BigMul in the method class.
I'm creating 100 instances of each of these classes, just to prevent and overflow of the lists (I can't create a 1000000000 items list).
I then measure the time it takes for each of the 100 classes to execute. The results are pretty peculiar : I've did this process about 15 times and the average results were (in milliseconds) :
Operator = 20357
Method = 24579
That about 4.5 seconds difference, which I think is a lot. I've looked at the source code of the BigMul method - it uses the * operator, and practically does the same exact thing.
So, for my quesitons :
Why such method even exist? It does exactly the same thing.
If it does exactly the same thing, why there is a huge efficiency difference between these two?
I'm just curious :)
Microbenchmarking is art. You are right the method is around 10% slower on x86. Same speed on x64. Note that you have to multiply two longs, so ((long)i) * ((long)i), because it is BigMul!
Now, some easy rules if you want to microbenchmark:
A) Don't allocate memory in the benchmarked code... You don't want the GC to run (you are enlarging the List<>)
B) Preallocate the memory outside the timed zone (create the List<> with the right capacity before running the code)
C) Run at least once or twice the methods before benchmarking it.
D) Try to not do anything but what you are benchmarking, but to force the compiler to run your code. For example checking for an always true condition based on the result of the operation, and throwing an exception if it is false is normally good enough to fool the compiler.
static void Main()
{
// Check x86 or x64
Console.WriteLine(IntPtr.Size == 4 ? "x86" : "x64");
// Check Debug/Release
Console.WriteLine(IsDebug() ? "Debug, USELESS BENCHMARK" : "Release");
// Check if debugger is attached
Console.WriteLine(System.Diagnostics.Debugger.IsAttached ? "Debugger attached, USELESS BENCHMARK!" : "Debugger not attached");
// High priority
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Stopwatch MulOperatorWatch = new Stopwatch();
Stopwatch MulMethodWatch = new Stopwatch();
// Prerunning of the benchmarked methods
MulMethodClass.start();
MulOperatorClass.start();
{
// No useless method allocation here
MulMethodWatch.Start();
for (int i = 0; i < 100; i++)
{
MulMethodClass.start();
}
MulMethodWatch.Stop();
}
{
// No useless method allocation here
MulOperatorWatch.Start();
for (int i = 0; i < 100; i++)
{
MulOperatorClass.start();
}
MulOperatorWatch.Stop();
}
Console.WriteLine("Operator = " + MulOperatorWatch.ElapsedMilliseconds.ToString());
Console.WriteLine("Method = " + MulMethodWatch.ElapsedMilliseconds.ToString());
Console.ReadLine();
}
public class MulOperatorClass
{
// The method is static. No useless memory allocation
public static void start()
{
for (int i = 2; i < 15000000; i++)
{
// This condition will always be false, but the compiler
// won't be able to remove the code
if (((long)i) * ((long)i) == ((long)i))
{
throw new Exception();
}
}
}
}
public class MulMethodClass
{
public static void start()
{
// The method is static. No useless memory allocation
for (int i = 2; i < 15000000; i++)
{
// This condition will always be false, but the compiler
// won't be able to remove the code
if (Math.BigMul(i, i) == i)
{
throw new Exception();
}
}
}
}
private static bool IsDebug()
{
// Taken from http://stackoverflow.com/questions/2104099/c-sharp-if-then-directives-for-debug-vs-release
object[] customAttributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
if ((customAttributes != null) && (customAttributes.Length == 1))
{
DebuggableAttribute attribute = customAttributes[0] as DebuggableAttribute;
return (attribute.IsJITOptimizerDisabled && attribute.IsJITTrackingEnabled);
}
return false;
}
E) If you are really sure your code is ok, try changing the order of the tests
F) Put your program in higher priority
but be happy :-)
at least another persons had the same question, and wrote a blog article: http://reflectivecode.com/2008/10/mathbigmul-exposed/
He did the same errors you did.

Manually terminate recursion

I have written a recursion (actually I found the recursion online) to get all possible permutations of a set of numbers but in some occasions, due to the large number of possible permutations, I would like to add an If statement to terminate the recursion before it goes through all permutations. I have tried entering a return statement but it doesn't seem to work.
I am a bit of a newbie in coding so apologies if the answer obvious to everyone, I just cannot get it.
class EntryPoint
{
static void Main()
{
//input an initial sequence of the trains to schedule
Console.Write("Input train permutation");
string inputLine = Console.ReadLine();
GenerateTrainOrder GTO = new GenerateTrainOrder();
GTO.InputSet = GTO.MakeCharArray(inputLine);
GTO.CalcPermutation(0);
}
}
class GenerateTrainOrder
{
private int elementLevel = -1; // elements examined iterates immediately after the CalcPermutation initiates so we must set it equal -1 to start from 0
private int[] permutationValue = new int[0];
public int[,] Paths = new int[ParametersClass.timetableNumber, ParametersClass.trainsToSchedule];
private char[] inputSet;
public char[] InputSet
{
get { return inputSet; }
set { inputSet = value; }
}
private int permutationCount = 0;
public int PermutationCount
{
get { return permutationCount; }
set { permutationCount = value; }
}
//transform the input from the console to an array for later use
public char[] MakeCharArray(string InputString)
{
char[] charString = InputString.ToCharArray();
Array.Resize(ref permutationValue, charString.Length);
return charString;
}
public void CalcPermutation(int k)
{
elementLevel++;
permutationValue.SetValue(elementLevel, k);
//if we have gone through all the elements which exist in the set, output the results
if (elementLevel == ParametersClass.trainsToSchedule)
{
OutputPermutation(permutationValue); // output TrainOrder by passing the array with the permutation
}
//if there are elements which have not been allocated a place yet
else
{
for (int i = 0; i < ParametersClass.trainsToSchedule; i++)
{
//iterate until we come upon a slot in the array which has not been allocated an elements yet
if (permutationValue[i] == 0)
{
CalcPermutation(i); //rerun the code to allocate an element to the empty slot. the location of the empty slot is given as a parameter (this is how k increments)
}
}
}
elementLevel--;
permutationValue.SetValue(0, k);
}
private void OutputPermutation(int[] value)
{
int slot = 0;
foreach (int i in value)
{
Paths[permutationCount, slot] = Convert.ToInt16(Convert.ToString(inputSet.GetValue(i-1)));
slot++;
}
PermutationCount++;
}
}
It is a bit tricky to stop a recursive calculation. The best method involves a global variable (or a private class variable if you have objects).
This variable says if the recursion should stop or not:
bool stopRecursion = false;
Now inside your calculation you update this variable after each step:
if(_my_condition_is_met) stopRecursion = true;
At the start of your recursively called method you check the state of this variable:
public void CalcPermutation(int k)
{
if(stopRecursion) return;
...
And you check this variable after each call to CalcPermutation:
for (int i = 0; i < ParametersClass.trainsToSchedule; i++)
{
//iterate until we come upon a slot in the array which has not been allocated an elements yet
if (permutationValue[i] == 0)
{
CalcPermutation(i);
if(stopRecursion) return;
....
With this method you unwind even deep call levels as soon as your stop condition is met.
Thanks for the replies everyone. I managed to make it work by doing the following:
Under the CalcPermutation(i) line, I wrote
if (permutationCount == ParametersClass.timetableNumber)
{
return;
}
I tried running it a few times with different inputs and it seems to work just fine.
for (int i = 0; i < ParametersClass.trainsToSchedule; i++)
{
//iterate until we come upon a slot in the array which has not been allocated an elements yet
if({your condition}){
break;
}
if (permutationValue[i] == 0)
{
CalcPermutation(i); //rerun the code to allocate an element to the empty slot. the location of the empty slot is given as a parameter (this is how k increments)
}
}

Thread causing IndexOutOfBounds Exception

This piece of code causes an IndexOutOfBoundsException
Can anyone please tell me why?
I can't undertstand why it is causing an IndexOutOfBoundsException
private static String TRACE_PATH = "..\\..\\TRACES";
static void Main(string[] args)
{
if (Directory.Exists(TRACE_PATH))
{
String[] traceEntries = Directory.GetFiles(TRACE_PATH);
Thread[] traceReaders = new Thread[traceEntries.Length];
for (int i = 0; i < traceEntries.Length; i++)
{
traceReaders[i] = new Thread(()=>readTrace(traceEntries[i]));
traceReaders[i].Start();
}
}
Console.Read();
}
private static void readTrace(String traceFile)
{
using (StreamReader sr = new StreamReader(traceFile))
{
//code to use the trace file...
}
}
Just declare a temp variable inside your loop. You are capturing the variable not the value.
for (int i = 0; i < traceEntries.Length; i++)
{
var j = i;
traceReaders[j] = new Thread(()=>readTrace(traceEntries[j]));
traceReaders[j].Start();
}
I'd prefer to write it this way.
for (int i = 0; i < traceEntries.Length; i++)
{
var traceEntry = traceEntries[i];
traceReaders[i] = new Thread(() => readTrace(traceEntry));
traceReaders[i].Start();
}
The explanation is that your variable i is send as parameter to a lambda expression. When the lamba expression is executed on the thread, your for loop will be already done, and thus i will be equal to the traceEnties.Length.
By declaring the traceEntry as local variable, you remove the dependency of the local variable i which is updated in the for loop.
The same thing happens in L.B.'s answer. It's a matter of taste how to deal with it I guess.

Regarding local variable passing in Thread

I'm having a hard time in understanding the unexpected output for the following program:
class ThreadTest
{
static void Main()
{
for(int i = 0; i < 10; i++)
new Thread(() => Console.Write(i)).Start();
}
}
Queries:
Different code running in different thread have seperate stacks? If yes, than variables should preserve their values as int is a value type?
Each thread gets its own stack. The problem that you are facing has nothing to do with stack. The problem is the way it is generating code for your anonymous delegate. Use tool like refelector to understand the code that it is generating. The following will fix your problem:
static void Main()
{
for (int i = 0; i < 10; i++)
{
int capture = i;
new Thread(() => Console.Write(capture)).Start();
}
}
Under the hood
Whenever you use a variable from outer scope (in your case variable i) in anonymous delegate, the compiler generates a new class that wraps anonymous function along with the data that it uses from the outer scope. So in your case the generated class contains - one function and data member to capture the value of variable i. The class definition looks something like:
class SomeClass
{
public int i { get; set; }
public void Write()
{
Console.WriteLine(i);
}
}
The compiler re-writes your code as follows:
SomeClass someObj = new SomeClass();
for (int i = 0; i < 10; i++)
{
someObj.i = i;
new Thread(someObj.Write).Start();
}
and hence the problem - that you are facing. When you capture a variable, the compiler does the following:
for (int i = 0; i < 10; i++)
{
SomeClass someObj = new SomeClass();
someObj.i = i;
new Thread(someObj.Write).Start();
}
Note the difference in SomeClass instantiation. When you capture a variable, it creates as many instances as there are number of iterations. If you do not capture a variable, it tries to use the same instance for all iterations.
Hope, the above explanation will clarify your doubt.
Thanks
Yes, threads have their own stacks. But here you also have an issue with variable capture. Try changing the code to:
class ThreadTest
{
static void Main()
{
for(int i = 0; i < 10; i++)
{
int j = i;
new Thread(() => Console.Write(j)).Start();
}
}
}
Notice the change in output? Each thread is being started with a reference to the variable, not the value. When I insert the int j = i; line, we are breaking the variable capture. Your unexpected output has less to do with threading than it does closures.

Categories