I am currently writing a program which requires me to have a pause between executing tasks.
So I have 4 things.
Read Limit
Delay Between Each Read
Total Reads
Global delay (pause the program for 'x' seconds after a task is finished)
Basically, one task is considered the "Read Limit". So, for example, if I have these settings:
Read Limit (10)
Delay Between Each Read (20)
Total Reads (100)
Global Delay (30)
The program has to read 10 lines from the file based on "Read Limit" and between reading each line, there is a delay of 20 seconds based on "Delay Between Each Read". After it reads 10 lines, it is paused for 30 seconds based on "Global Delay". When the global delay is over, it starts again where it stopped and continues doing this until the limit of 100 is reached based on "Total Reads".
I have tried using System.Threading.Thread.Sleep() but I couldn't make it work. How can I achieve this with C#?
Thanks in advance.
//update with some of my code.
I load the file like this:
private void btnLoadFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
string[] lines = System.IO.File.ReadAllLines(ofd.FileName);
}
}
I have 4 global variables:
public int readLimit = 0;
public int delayBetweenRead = 0;
public int totalReads = 0;
public int globalDelay = 0;
public int linesRead = 0;
And I want to make the function like this:
private void doTask()
{
while (linesRead <= readLimit)
{
readLine(); // read one line
doDelay(); // delay between each line
readLine(); // read another line and so on, until readLimit or totalReads is reached
globalDelay(); // after readLimit is reached, call globalDelay to wait
linesRead++;
}
}
This might be of interest - here's the way to do this with Microsoft's Reactive Framework (NuGet "Rx-Main").
int readLimit = 10;
int delayBetweenRead = 20;
int globalDelay = 30;
int linesRead = 100;
var subscription =
Observable
.Generate(0, n => n < linesRead, n => n + 1, n => n,
n => TimeSpan.FromSeconds(n % readLimit == 0 ? globalDelay : delayBetweenRead))
.Zip(System.IO.File.ReadLines(ofd.FileName), (n, line) => line)
.Subscribe(line =>
{
/* do something with each line */
});
If you need to stop the reading before it finishes naturally just call subscription.Dispose();.
What you do you mean by
I have tried using System.Threading.Thread.Sleep() but I couldn't make it work
Here is an example of achieving what you described with Thread.Sleep:
using (var fs = new FileStream("C:\\test.txt", FileMode.Open, FileAccess.Read))
{
using (var sr = new StreamReader(fs))
{
int nRead = 0;
while (nRead < settings.Total)
{
for (int i = 0; i < settings.ReadLimit && nRead < settings.Total; ++i, nRead++)
{
Console.WriteLine(sr.ReadLine());
if (i + 1 < settings.ReadLimit)
{
Thread.Sleep(settings.Delay * 1000);
}
}
if (nRead < settings.Total)
{
Thread.Sleep(settings.GlobalDelay * 1000);
}
}
}
}
Related
I have a very specific and demanding workload I am trying to multithreaded. This is very new to me so I am struggling to find an effective solution.
Program Description: UpdateEquations() is cycling through a list of mathematical functions to update the coordinates of rendered lines. By default, func.Count = 3, so this will call CordCalc() 1500 times every frame. I am using NClac to parse a function string and write the result to the Function list, which will later be used before the end of the frame (irrelevant).
Goal: I want to put each cycle of the for(int a) loop inside its own thread. Since for(int a) will only loop 3 times, I just need to start three threads. I cannot continue the for(int i) loop until for(int a) is fully calculated. I am calculating a very large about of small tasks so it would be too expensive to assign each task to the thread.
What I am currently trying to do: I am trying to use a ThreadPool queue, however I'm not sure how to wait for them all to finish before continuing onto the next for(int i) iteration. Furthermore, while the program compiles and executes, the performance is disastrous. Probably %5 of my original performance. I am not sure if creating a "new WaitCallback" is expensive or not. I was looking for a way to predefined threads somehow so that I don't have to reinitialize them 1500 times a frame. (Which is what I suspect the issue is).
Other things I've tried: I tried using new Thread(() => CordCalc(a, i)); however this seemed to have much worse performance. I saw online somewhere that using a ThreadPool would be less expensive.
(This code is shortened for readability and relevance)
public List<Function> func;
private Expression[] exp;
private int lines_i;
private int lines_a;
public void Start()
{
func = new List<Function>();
exp = new Expression[func.Count];
for (int i = 0; i < func.Count; i++) exp[i] = new Expression(func[i].function);
}
//Calculate
public void CordCalc(object state)
{
for (int b = 0; b < func.Count; b++)
exp[lines_a].Parameters[func[b].name] = func[b].mainCords[lines_i - 1];
exp[lines_a].Parameters["t"] = t;
try
{
func[lines_a].mainCords[lines_i] = Convert.ToSingle(exp[lines_a].Evaluate());
}
catch
{
Debug.Log("input Error");
func[lines_a].mainCords[lines_i] = 0;
}
}
private void UpdateEquations()
{
//Initialize equations
for (int a = 0; a < func.Count; a++)
{
func[a].mainCords[0] = t;
}
lines_i = 1;
for (int i = 1; i < 500; i++)
{
lines_a = 0;
for (int a = 0; a < func.Count; a++)
{
//Calculate
ThreadPool.QueueUserWorkItem(new WaitCallback(CordCalc));
//This was something else that I tried, which gave worse results:
//threads[a] = new Thread(() => CordCalc(a, i));
//threads[a].Start();
//t.Join();
//This was my original method call without multithreading
//func[a].mainCords[i] = CordCalc(a, i);
lines_a++;
}
lines_i++;
}
private void FixedUpdate()
{
t += step * (2 + step) * 0.05f;
UpdateEquations();
}
//Function List
public class Function
{
public string name;
public string function;
public float[] mainCords;
//Constructor
public Function(string nameIn, string funcIn)
{
name = nameIn;
function = funcIn;
}
public void SetSize(int len)
{
mainCords = new float[len];
}
}
I have this simple function that is used to generate neuron connections position:
using System.Collections.Generic;
using System.Drawing;
public static List<Point> GetConnectionsConnectedPosition(int connectedLayerI, int startingConnectedNeuronIndex, int outputLength)
{
var connections = new List<Point>();
for (int i = 0; i < outputLength; i++)
{
connections.Add(new Point(connectedLayerI, startingConnectedNeuronIndex + i));
}
return connections;
}
And now I want to create all the connections positions for a specific neuron connections using this constructor code:
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
internal NeuronConnectionsInfo(int layerIndex, int previousLayerLength, double minWeight, double maxWeight, double valueClosestTo0)
{
Weights = new List<double>();
ConnectedNeuronsPos = new List<Point>();
int connectionsPerTask = 750;
// specify task job
int taskCount = previousLayerLength / connectionsPerTask;
int leftConnectionCount = previousLayerLength % connectionsPerTask;
// Initialize tasks
List<Task<List<double>>> weigthsTasks = new List<Task<List<double>>>();
List<Task<List<Point>>> positionsTasks = new List<Task<List<Point>>>();
for (int i = 0; i < taskCount; i++)
{
weightsTasks.Add(Task.Run(() => GenerateWeigths(connectionsPerTask, minWeigth, maxWeight, valueClosestTo0));
positionsTasks.Add(Task.Run(() => GetConnectionsConnectedTo(layerIndex - 1, connectionsPerTask * i, connectionsPerTask);
}
weightsTasks.Add(Task.Run(() => GenerateWeights(connectionsPerTask, minWeight, maxWeight, valueClosestTo0));
positionsTasks.Add(Task.Run(() => GetConnectionsConnectedTo(layerIndex - 1, connectionsPerTask * taskCount, leftConnectionsCount));
//wait for tasks to finish
bool isFinished = false;
while (!isFinished)
{
isFinished = true;
Thread.Sleep(20);
foreach (weightsTask in weightsTasks)
{
isFinished = isFinished && weightTask.IsCompleted;
}
if (isFinished)
foreach (positionTask in positionsTasks)
{
isFinished = isFinished && positionTask.isCompleted;
}
}
for (int i = 0; i < weightsTasks; i++)
{
Weights.AddRange(weightsTasks[i].Result);
ConnectedNeuronsPos.AddRange(positionsTasks[i].Result);
}
}
Weights are being generated alright, but the problem begins with positions' X (connectedLayerI) starting at connectionsPerTask * taskCount, basically position's X starting where the last task X position should start even though y (connectedNeuronI) is being generated ok and Task's result length is also being generated alright.
While debugging I noticed that if I executed the instructions at a human speed the result was alright, then, I tried adding Thread.Sleep(20); before and after calling Task.Run(() => GetConnectionsConnectedTo(...));
This seems to solve the issue but I'm not confident that it'll solve the issue with all processors because it seems to be an error with C#'s static programming.
All answers will be accepted so don't have any hesitation on answering with your opinion or with a more optimized or secure method.
Thanks in advance.
I'm reading a file and wants to process 10 lines at a time.
This only works if I'm processing < 10 lines. For loop just continues and doesn't wait for the first 10 tasks to complete.
Please advise.
Below is my code :
private void btnStart_Click(object sender, EventArgs e)
{
int lctr = 0;
var tasks = new List<Task>();
foreach (string s in lines)
{
if (string.IsNullOrWhiteSpace(s) || string.IsNullOrEmpty(s))
continue;
lctr++;
tasks = new List<Task>();
if (lctr < 11)
{
Console.WriteLine(lctr + " - " + s);
tasks.Add(Task.Factory.StartNew(() => processThis(s)));
}
else
{
Console.WriteLine("Waiting ...");
Task.WaitAll(tasks.ToArray());
}
}
if (tasks.Count > 0)
Task.WaitAll(tasks.ToArray());
}
When you say "Please Advise" it gives me wide latitude to try and help. Here are my suggestions and I hope you find them "useful":
Q: "I'm reading a file and wants to process 10 lines at a time."
A: Before spawning any tasks, enqueue your test list into groups of 10 strings (and a final group that might be partial if, say, the list is 25 string long).
Here is a method to do the first part:
// Short-running method that queues up strings in batches of 10 or less
private static Queue<List<string>> enqueueBatchesOf10orLess(List<string> testData)
{
Queue<List<string>> batchesOfUpTo10 = new Queue<List<string>>();
List<string> singleBatchOfUpTo10 = new List<string>(); ;
for (int count = 0; count < testData.Count; count++)
{
if ((count % 10) == 0)
{
if(count != 0) // Skip the very first time
{
batchesOfUpTo10.Enqueue(singleBatchOfUpTo10);
singleBatchOfUpTo10 = new List<string>();
}
}
singleBatchOfUpTo10.Add(testData[count]);
}
// Leftover batch of less-than-10
if(singleBatchOfUpTo10.Count != 0)
{
batchesOfUpTo10.Enqueue(singleBatchOfUpTo10);
}
return batchesOfUpTo10;
}
Next, it appears you want to process those batches concurrently (implying that there might be some processing time that justifies doing this). Here is how you pass your "batches of 10 or less" in and receive a Task in return.
private static Task processBatch(Queue<List<string>> batches)
{
return Task.Run(() => // Return task that processes batch of 10 or less
{
var batch = batches.Dequeue();
foreach (var singleString in batch)
{
processThis(singleString);
}
});
}
...where...
private static void processThis(string s)
{
Task.Delay(100).Wait(); // Simulate long-running string processing
Console.WriteLine(s);
}
To test this out:
static void Main(string[] args)
{
// Make some test data
List<string> testData = new List<string>();
for (int i = 0; i < 25; i++) testData.Add((i + 1).ToString());
Queue<List<string>> batchesOf10OrLess = enqueueBatchesOf10orLess(testData);
List<Task> tasks = new List<Task>();
for (int i = 0; i < batchesOf10OrLess.Count; i++)
{
// Pass in the queue of batches and get a Task in return.
tasks.Add(processBatch(batchesOf10OrLess));
}
Console.WriteLine("The test data is NOT in order.");
Console.WriteLine("This is proof the tasks are running concurrently");
Task.WaitAll(tasks.ToArray());
// Pause
Console.ReadKey();
}
Here's what we get:
The test data is NOT in order.
This is proof the tasks are running concurrently
1
21
11
2
12
22
3
23
13
4
14
24
5
25
15
6
16
7
17
8
18
19
9
10
20
If you like download this sample from GitHub.
I have a code with threads and I want to show the pending time to finish processing. The button1 calls the
function "Function1()" that reads a file in chunks of 1024 bytes controlled in a while loop until get end
of file. Within the "While loop" there is a "foreach loop" where is called the "Function2()". I'm starting
the timer at the beginning of "while loop" and stopping it at the end of "while loop". After that I'm trying
to calculate aprox the Pending time knowing first the number of iterations that will be processed by "while loop".
Then I save the "elapsed time for the first iteration" (lets say T1) and then I multiply it by number of iterations.
This would be
PendingTime = T1*Iterations.
Then I do
PendingTime = PendingTime - Ti, where Ti is the ElapsedTime of the ith iteration.
The issue is when I try with the real code, the multiplation of T1*Iterations gives me 402s and actually
the processing takes 12s.
Maybe some expert could see what I'm doing wrong. Thanks in advance.
The code looks like this:
async void button1_Click(object sender, EventArgs e)
{
//Some code
await Task.Run(() => Function1(inputfile, cts.Token), cts.Token);
//Some code
}
public void Function2()
{
//Some code
}
public void Function1(string inputfile, CancellationToken token)
{
int buffer = 1024;
int IterationCounter = 0;
decimal Iterations = 1;
int PendingTime = 0;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
FileLength = (int)reader.BaseStream.Length;
Iterations = (int)FileLength/buffer;
while (chunk.Length > 0)
{
Stopwatch sw1 = Stopwatch.StartNew(); //Start time counter
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//some code
chunk = reader.ReadBytes(buffer);
foreach (byte data in chunk)
{
//Some code
Function2(); //Call to Function2
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Checking if it is the first iteration to save the pending time
//Pending time would be the elapsed time for the first iteration
//multiplied by the number of iterations (FileLength/1024).
sw1.Stop(); //Stop time counter
if (IterationCounter == 1)
{
PendingTime = (int)((decimal)Math.Round(sw1.Elapsed.TotalMilliseconds / 1000, 4)*Iterations);
}
//Show in TexBox1 the pending time
TextBox1.Invoke((MethodInvoker)delegate
{
PendingTime = PendingTime - (int)Math.Round(sw1.Elapsed.TotalMilliseconds / 1000, 4);
TextBox1.Text = PendingTime + " s";
});
}
}
}
Update:
I'm testing with the following code based on the example of Peter Duniho.
It can be tested with any file(i.e. txt file). I've tested with a txt file of 5MB and execution time was 3 seconds, but the pending time appear always as zero in TextBox1. Where I'm wrong?
Note: I changed this:
double timePerIteration = sw1.Elapsed / ++IterationCounter;
to this
double timePerIteration = sw1.ElapsedMilliseconds/1000/ ++IterationCounter;
Since I was getting the error:
Operator '/' cannot be applied to operands of type 'System.TimeSpan' and 'int' (CS0019)
The code so far is. Thanks for help.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestTimer
{
public partial class MainForm : Form
{
CancellationTokenSource cts = new CancellationTokenSource();
string filename = "";
long FileLength;
FileInfo fInfo;
Stopwatch sw1 = new Stopwatch();
public MainForm()
{
InitializeComponent();
}
void BtnSelectFileClick(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Select file";
DialogResult dr = ofd.ShowDialog();
if (dr == DialogResult.OK)
{
filename = ofd.FileName;
fInfo = new FileInfo(filename);
}
else
{
MessageBox.Show("File not found");
return;
}
}
async void BtnRunProcessClick(object sender, System.EventArgs e)
{
cts = new CancellationTokenSource();
await Task.Run(() => Function1(filename, cts.Token), cts.Token);
}
public void Function1(string inputfile, CancellationToken token)
{
int buffer = 1024;
int IterationCounter = 0;
int Iterations = 0;
double pendingTime = 0;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
FileLength = (int)reader.BaseStream.Length;
Iterations = (int)FileLength/buffer;
byte[] chunk;
sw1 = Stopwatch.StartNew(); //Start time counter
while (true)
{
chunk = reader.ReadBytes(buffer);
if (chunk.Length == 0) {break;}
foreach (byte data in chunk)
{
Thread.Sleep(90/100);
}
// pendingTime is the current average time-per-iteration,
// times the number of iterations left
double timePerIteration = sw1.ElapsedMilliseconds/1000/ ++IterationCounter;
pendingTime = timePerIteration * (Iterations - IterationCounter);
TextBox1.Invoke((MethodInvoker)delegate
{
// Let string.Format() take care of rounding for you
TextBox1.Text = string.Format("{0:0} s", pendingTime / 1000);
});
}
MessageBox.Show("Execution time: " + string.Format("{0:0} s", sw1.ElapsedMilliseconds / 1000) );
}
}
}
}
I don't see how the code you posted ever actually compiled, never mind worked. The FileLength variable does not appear to be declared, and you never increment the IterationCounter variable, giving you a negative PendingTime value with each iteration. Even if you had incremented the counter, your PendingTime variable's actual meaning changes from the block that executes when the counter is 1 and a little later when you subtract your elapsed time from the current PendingTime variable.
That suggests the code you posted isn't really the code you're using, since the displayed time remaining would always have been negative (even assuming the declaration of FileLength just got accidently dropped from your post for some reason). For the sake of argument, I'll add a statement that does the increment…
As commenter Chris says, when each iteration's actual duration can vary, as it seems to be the case here, the best you're going to do is average all of the iterations up to the current one. Even that may lead to an erroneous time-remaining display, with a fair amount of variation from iteration to iteration (especially if the number of iterations is small), but at least it's more likely to be close.
Something like this would likely work better for you:
public void Function1(string inputfile, CancellationToken token)
{
int buffer = 1024;
int IterationCounter = 0;
int Iterations;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
if (reader.BaseStream.Length == 0)
{
// nothing to do
return;
}
// NOTE: this won't work for files with length > int.MaxValue!
// Your original code has the same limitation, and I have not
// bothered to change that.
// Now that we know for sure the length is > 0, we can
// do the following to ensure a correct iteration count
Iterations = ((int)reader.BaseStream.Length - 1) / buffer + 1;
Stopwatch sw1 = Stopwatch.StartNew();
while (chunk.Length > 0)
{
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//some code
chunk = reader.ReadBytes(buffer);
foreach (byte data in chunk)
{
//Some code
Function2(); //Call to Function2
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// pendingTime is the current average time-per-iteration,
// times the number of iterations left
double timePerIteration = sw1.ElapsedMilliseconds / ++IterationCounter,
pendingTime = timePerIteration *
(Iterations - IterationCounter);
//Show in TexBox1 the pending time
TextBox1.Invoke((MethodInvoker)delegate
{
// Let string.Format() take care of rounding for you
TextBox1.Text = string.Format("{0:0} s", pendingTime / 1000);
});
}
}
}
Unless you are guaranteed that your input file is always exactly a multiple of 1024 bytes in length, you also had a bug in your calculation of the total iteration count. I fixed that in the above as well.
I am writing dice roller program in C# console. I am giving two input
Enter the size of the dice and
Enter how times you want to play.
Suppose dice size is 6 and 10 times i have played.
Output is coming:
1 was rolled 2 times
2 was rolled 7 times
3 was rolled 8 times
4 was rolled 7 times
5 was rolled 4 times
6 was rolled 5 times
Total: 33 (its not fixed for every execution this no will be changed)
But my requirement was this total always should be number of playing times. Here I am playing 10 times so the total should be 10 not 33. It should happen for every new numbers... If I play 100 times sum or total should be 100 only not any other number. rest all will be remain same, in my programing not getting the expected sum. Please somebody modify it. Here is my code:
Dice.cs:
public class Dice
{
Int32 _DiceSize;
public Int32 _NoOfDice;
public Dice(Int32 dicesize)
{
this._DiceSize = dicesize;
}
public string Roll()
{
if (_DiceSize<= 0)
{
throw new ApplicationException("Dice Size cant be less than 0 or 0");
}
if (_NoOfDice <= 0)
{
throw new ApplicationException("No of dice cant be less than 0 or 0");
}
Random rnd = new Random();
Int32[] roll = new Int32[_DiceSize];
for (Int32 i = 0; i < _DiceSize; i++)
{
roll[i] = rnd.Next(1,_NoOfDice);
}
StringBuilder result = new StringBuilder();
Int32 Total = 0;
Console.WriteLine("Rolling.......");
for (Int32 i = 0; i < roll.Length; i++)
{
Total += roll[i];
result.AppendFormat("{0}:\t was rolled\t{1}\t times\n", i + 1, roll[i]);
}
result.AppendFormat("\t\t\t......\n");
result.AppendFormat("TOTAL: {0}", Total);
return result.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter no of dice size");
int dicesize = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("How many times want to play");
int noofplay=Convert.ToInt32(Console.ReadLine());
Dice obj = new Dice(dicesize);
obj._NoOfDice = noofplay;
obj.Roll();
Console.WriteLine(obj.Roll());
Console.WriteLine("Press enter to exit");
Console.ReadKey();
}
}
It looks to me like you're getting the math backwards... shouldn't it be:
// to capture just the counts
int[] roll = new int[_DiceSize];
for (int i = 0; i < _NoOfDice; i++)
{
roll[rnd.Next(roll.Length)]++;
}
Or if you want the actual rolls:
// to capture individual rolls
int[] roll = new int[_NoOfDice];
for (int i = 0; i < _NoOfDice; i++)
{
roll[i] = rnd.Next(_DiceSize) + 1; // note upper bound is exclusive, so +1
}
You are creating a new Random instance on each iteration. This is not a good thing as it will affect the uniform distribution of results. Keep the Random instance in a field instead of creating a new one every time.
public class Dice {
private Random rnd = new Random();
// ... don't create a new random in `Roll` method. Use `rnd` directly.
}
First of all, the following for-loop is wrong:
for (Int32 i = 0; i < _DiceSize; i++)
{
roll[i] = rnd.Next(1,_NoOfDice);
}
Obviously you switched _DiceSize and _NoOfDice. The correct loop would look like
for (Int32 i = 0; i < _NoOfDice; i++)
{
roll[i] = rnd.Next(1,_DiceSize);
}
Because of that, the line
Int32[] roll = new Int32[_DiceSize];
has to be changed to
Int32[] roll = new Int32[_NoOfDice];
Maybe you should think about renaming these variables, so it's more clearly, which means what.
If you modify your code that way, you will mention that your analisys won't work that way you implemented it. Actually, what you are showing is the result of each throw, which is not what you want, if I understood you right.
UPDATE:
Sorry, I misunderstood you. You do want to show the result for every roll. So, why don't you just move the StringBuilder.AppendFormat to your "rolling-for-loop"?
UPDATE #2:
For me, the following Die-class works exactly the way you want it:
public class Die
{
private int maxValue;
private int numberOfRolls;
private Random random;
public Die(int maxValue, int numberOfRolls)
{
this.maxValue = maxValue;
this.numberOfRolls = numberOfRolls;
this.random = new Random();
}
public string Roll()
{
StringBuilder resultString = new StringBuilder();
for (int i = 0; i < this.numberOfRolls; i++)
{
resultString.AppendFormat("Roll #{0} - Result: {1}" + Environment.NewLine, i + 1, this.random.Next(1, maxValue + 1));
}
return resultString.ToString();
}
}
Hope I could help you.
This is the full code you have to use, according to Mehrdad and Marc Gravell.
Have fun.
public class Dice
{
private Random rnd = new Random();
Int32 _DiceSize;
public Int32 _NoOfDice;
public Dice(Int32 dicesize)
{
if (dicesize <= 0)
{
throw new ApplicationException("Dice Size cant be less than 0 or 0");
}
this._DiceSize = dicesize;
}
public string Roll()
{
if (_NoOfDice <= 0)
{
throw new ApplicationException("No of dice cant be less than 0 or 0");
}
// to capture just the counts
int[] roll = new int[_DiceSize];
for (int i = 0; i < _NoOfDice; i++)
{
roll[rnd.Next(roll.Length)]++;
}
StringBuilder result = new StringBuilder();
Int32 Total = 0;
Console.WriteLine("Rolling.......");
for (Int32 i = 0; i < roll.Length; i++)
{
Total += roll[i];
result.AppendFormat("{0}:\t was rolled\t{1}\t times\n", i + 1, roll[i]);
}
result.AppendFormat("\t\t\t......\n");
result.AppendFormat("TOTAL: {0}", Total);
return result.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter no of dice size");
int dicesize = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("How many times want to play");
int noofplay = Convert.ToInt32(Console.ReadLine());
Dice obj = new Dice(dicesize);
obj._NoOfDice = noofplay;
Console.WriteLine(obj.Roll());
Console.WriteLine("Press enter to exit");
Console.ReadKey();
}
}