I'm new to programming and currently I'm trying to learn c#. Here is my question:
I have this following piece of code:
static void Main()
{
string loading = "LOADING...";
for (int i = 0; i < 5; i++)
{
foreach (var letter in loading)
{
Console.Write("{0}", letter);
Thread.Sleep(250);
}
Console.Clear();
Console.Write("\r");
}
for (int k = 0; k <= 100; k++)
{
Console.Write("\r{0}%", k);
Thread.Sleep(150);
}
}
I am trying to find a way to execute these two for loops simultaneously. I want to keep re-writing LOADING on the console and under it to print the percentage from 1 to 100. Right now the second for loop runs after the first quits. Is it possible to make them run at the same time? I have been trying to find an answer for a few hours now, but with no luck so far.
Thanks!
As krillgar noted you can use Tasks to run each loop independently. Something like this:
string loading = "LOADING...";
var loadingTask = Task.Run(() =>
{
for (int i = 0; i < 5; i++)
{
foreach (var letter in loading)
{
Console.Write("{0}", letter);
Thread.Sleep(250);
}
Console.Clear();
Console.Write("\r");
}
});
var pocTask = Task.Run(() =>
{
for (int k = 0; k <= 100; k++)
{
Console.Write("\r{0}%", k);
Thread.Sleep(150);
}
});
Task.WaitAll(loadingTask, pocTask);
Please note however it'll not work as you would expect( first line with LOADING... and second with percentage). That would require some synchronization of displayed messages between those loops and I think that's whole another story and not in the scope of the answer to your question.
There is more to this challenge than just running the code in two threads. When multiple threads are attempting to write to the console simultaneously, you are likely to end up with race conditions, where one thread starts writing in the middle of another thread's output.
To protect against this, you need to enforce critical sections, which are regions of your code where only one thread can execute at any time. These would generally consist of:
// Critical section
lock (syncLock)
{
Console.SetCursorPosition(x, y);
Console.Write(yourText);
}
Thread.Sleep(yourDelay);
Here is the full code:
// Dummy object to serve as mutual-exclusion lock when synchronizing threads.
private static readonly object syncLock = new object();
public static void Main(string[] args)
{
// Run two anonymous functions in parallel,
// then wait for both to complete.
Parallel.Invoke(
// Anonymous function for printing "LOADING..."
() =>
{
const string loading = "LOADING...";
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < loading.Length; j++)
{
// Critical section
lock (syncLock)
{
Console.SetCursorPosition(j, 0);
Console.Write("{0}", loading[j]);
}
Thread.Sleep(250);
}
// Critical section
lock (syncLock)
{
Console.SetCursorPosition(0, 0);
Console.Write("\r ");
}
Thread.Sleep(250);
}
},
// Anonymous function for printing "x%"
() =>
{
for (int k = 0; k <= 100; k++)
{
// Critical section
lock (syncLock)
{
Console.SetCursorPosition(0, 1);
Console.Write("\r{0}%", k);
}
Thread.Sleep(150);
}
});
}
}
Related
I created a method for writing a text slowly for a game.
The problem is, when the method is running and I select something with mouse in cmd window, the whole program freezes and when I press escape it continues. Is there something I can do so it won't happen? Can I use something different than System.Threading.Thread.Sleep() for my program to wait?
static void slowly(string sen)
{
for (int j=0; j<sen.Length-1; j++)
{
Console.Write(sen[j]);
System.Threading.Thread.Sleep(100);
}
Console.WriteLine(sen[sen.Length-1]);
System.Threading.Thread.Sleep(100);
}
The problem is that your sleep code is running on the "Main Thread" of your application. This means that your application can't really do anything else while it's in the .slowly() method.
You need to do something like what #vidstige shows, which is to have your .slowly() method run in another (helper) thread.
A more modern approach would be to:
static async Task slowly(string sen)
{
await Task.Run(() =>
{
for (int j = 0; j < sen.Length - 1; j++)
{
Console.Write(sen[j]);
System.Threading.Thread.Sleep(100);
}
Console.WriteLine(sen[sen.Length - 1]);
System.Threading.Thread.Sleep(100);
});
}
public static void Main(string[] args)
{
var slowlyTask = slowly("hello world");
//do stuff while writing to the screen
var i = 0;
i++;
//wait for text to finish writing before doing somethign else
slowlyTask.Wait();
//do another something after it's done;
var newSlowlyTask = slowly("goodbye");
newSlowlyTask.Wait();
}
PS: The amount of negative responses to this question is disappointing :(
static void slowly(string sen)
{
var thread = new System.Threading.Thread(() => {
for (int j=0; j<sen.Length-1; j++)
{
System.Console.Write(sen[j]);
System.Threading.Thread.Sleep(100);
}
System.Console.Write(sen[sen.Length-1]);
System.Threading.Thread.Sleep(100);
});
thread.Start();
}
I have main and working threads. These working threads must not stopped before main task is over (i.e. i cant re-creating them with Thread.Start()). These working threads reading data from main thread, then writing other data and then main thread writing it in file.
I must use NET 3.5, not including ThreadPool and BackgroundWorker
InFile -> RawData -> Working -> ReadyData -> OutFile.
public func(string InputFile,string outputFile) {
...
for(int i=0;i<ThreadCount;i++)
{
CompressorThreads[i] = new Thread(new ParameterizedThreadStart(CompressBlock));
ThreadParam thr = new ThreadParam(i);
CompressorThreads[i].Start(thr);
}
int count;
while (InputFile.Position < InputFile.Length)
{
for (int i = 0; i < ThreadCount; i++)
{
count = InputFile.Read(buffer, 0, BLOCK_SIZE);
RawData[i] = new byte[count];
/*here activating(start) thread*/
}
for (int i = 0; (i < ThreadCount) && (CompressorThreads[i] != null);)
{
/*prevent(pause) working thread from changing CompressedData*/
OutputFile.Write(CompressedData[i], 0, CompressedData[i].Length);
}
}
...
}
private static void CompressBlock(object BlockProperties)
{
ThreadParam Block = BlockProperties as ThreadParam;
int ThreadId = Block.ThreadId;
while (true)
{
if(RawData[ThreadId].Length == 0)
{
break;
}
...
/*working here*/
...
/*then save data to CompressedData*/
/*pause thread*/
}
}
I tried AutoResetEvent, but it seems inappropriate for this problem. What i'm looking for?
I want to create a multithreaded application code. I want to execute configured no of threads and each thread do the work. I want to know is this the write approach or do we have better approach. All the threads needs to be executed asynchronously.
public static bool keepThreadsAlive = false;
static void Main(string[] args)
{
Program pgm = new Program();
int noOfThreads = 4;
keepThreadsAlive = true;
for (int i = 1; i <= noOfThreads; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), (object)i);
}
System.Console.ReadLine();
StopAllThreads();
System.Console.ReadLine();
}
private static void DoWork(object threadNumber)
{
int threadNum = (int)threadNumber;
int counter = 1;
while (keepThreadsAlive)
{
counter = ProcessACK(threadNum, counter);
}
}
private static int ProcessACK(int threadNum, int counter)
{
System.Console.WriteLine("Thread {0} count {1}", threadNum, counter++);
Random ran = new Random();
int randomNumber = ran.Next(5000, 100000);
for (int i = 0; i < randomNumber; i++) ;
Thread.Sleep(2000);
return counter;
}
As others have pointed out, the methods you are using are dated and not as elegant as the more modern C# approach to accomplishing the same tasks.
Have a look at System.Threading.Tasks for an overview of what is available to you these days. There is even a way to set the maximum threads used in a parallel operation. Here is a simple (pseudocode) example:
Parallel.ForEach(someListOfItems, new ParallelOptions { MaxDegreeOfParallelism = 8 }, item =>
{
//do stuff for each item in "someListOfItems" using a maximum of 8 threads.
});
Hope this helps.
why is it, that in the following code, n doesn't end up being 0, it's some random number with a magnitude less than 1000000 each time, somtimes even a negative number?
static void Main(string[] args)
{
int n = 0;
var up = new Thread(() =>
{
for (int i = 0; i < 1000000; i++)
{
n++;
}
});
up.Start();
for (int i = 0; i < 1000000; i++)
{
n--;
}
up.Join();
Console.WriteLine(n);
Console.ReadLine();
}
Doesn't up.Join() force both for loops to finish before WriteLine is called?
I understand that the local variable is actually part of a class behind the scenes (think it's called a closure), however because the local variable n is actually heap allocated, would that affect n not being 0 each time?
The n++ and n-- operations are not guaranteed to be atomic. Each operation has three phases:
Read current value from memory
Modify value (increment/decrement)
Write value to memory
Since both of your threads are doing this repeatedly, and you have no control over the scheduling of the threads, you will have situations like this:
Thread1: Get n (value = 0)
Thread1: Increment (value = 1)
Thread2: Get n (value = 0)
Thread1: Write n (n == 1)
Thread2: Decrement (value = -1)
Thread1: Get n (value = 1)
Thread2: Write n (n == -1)
And so on.
This is why it is always important to lock access to shared data.
-- Code:
static void Main(string[] args)
{
int n = 0;
object lck = new object();
var up = new Thread(() =>
{
for (int i = 0; i < 1000000; i++)
{
lock (lck)
n++;
}
});
up.Start();
for (int i = 0; i < 1000000; i++)
{
lock (lck)
n--;
}
up.Join();
Console.WriteLine(n);
Console.ReadLine();
}
-- Edit: more on how lock works...
When you use the lock statement it attempts to acquire a lock on the object you supply it - the lck object in my code above. If that object is already locked, the lock statement will cause your code to wait for the lock to be released before continuing.
The C# lock statement is effectively the same as a Critical Section. Effectively it is similar to the following C++ code:
// declare and initialize the critical section (analog to 'object lck' in code above)
CRITICAL_SECTION lck;
InitializeCriticalSection(&lck);
// Lock critical section (same as 'lock (lck) { ...code... }')
EnterCriticalSection(&lck);
__try
{
// '...code...' goes here
n++;
}
__finally
{
LeaveCriticalSection(&lck);
}
The C# lock statement abstracts most of that away, meaning that it's much harder for us to enter a critical section (acquire a lock) and forget to leave it.
The important thing though is that only your locking object is affected, and only with regard to other threads trying to acquire a lock on the same object. Nothing stops you from writing code to modify the locking object itself, or from accessing any other object. YOU are responsible for making your sure your code respect the locks, and always acquires a lock when writing to a shared object.
Otherwise you're going to have a non-deterministic outcome like you've seen with this code, or what the spec-writers like to call 'undefined behavior'. Here Be Dragons (in the form of bugs you'll have endless trouble with).
Yes, up.Join() will ensure that both of the loops end before WriteLine is called.
However, what is happening is that the both of the loops are being executed simultaneously, each one in it's own thread.
The switching between the two threads is done all the time by the operation system, and each program run will show a different switching timing set.
You should also be aware that n-- and n++ are not atomic operations, and are actually being compiled to 3 sub-operations, e.g.:
Take value from memory
Increase it by one
Put value in memory
The last piece of the puzzle, is that the thread context switching can occur inside the n++ or n--, between any of the above 3 operations.
That is why the final value is non-deterministic.
If you don't want to use locks there are atomic versions of the increment and decrement opperators in the Interlocked class.
Change your code to the following and you will always get 0 for an answer.
static void Main(string[] args)
{
int n = 0;
var up = new Thread(() =>
{
for (int i = 0; i < 1000000; i++)
{
Interlocked.Increment(ref n);
}
});
up.Start();
for (int i = 0; i < 1000000; i++)
{
Interlocked.Decrement(ref n);
}
up.Join();
Console.WriteLine(n);
Console.ReadLine();
}
You need to join the threads earlier:
static void Main(string[] args)
{
int n = 0;
var up = new Thread(() =>
{
for (int i = 0; i < 1000000; i++)
{
n++;
}
});
up.Start();
up.Join();
for (int i = 0; i < 1000000; i++)
{
n--;
}
Console.WriteLine(n);
Console.ReadLine();
}
I have n number of threads which run a method routine. With each thread running the search method, and searching for items in a given range, the items are retrieved from a web server. But I believe that they keep on running, even when the range is exhausted. I am using a for loop to determine when the thread should stop searching, but that is not working out. This is what I have:
In method Start() I compute a certain range, and that range is given to a thread, which is to search in this given range.
public void Start()
{
this.totalRangePerThread = ((this.endRange - this.startRange) / this.subWorkerThreads.Length);
for (int i = 0; i < this.subWorkerThreads.Length; ++i)
{
var copy = startRange;
this.subWorkerThreads[i] = new Thread(() => searchItem(copy, this.totalRangePerThread));
this.startRange = this.startRange + this.totalRangePerThread;
}
for (int threadIndex = 0; threadIndex < this.subWorkerThreads.Length; ++threadIndex)
this.subWorkerThreads[threadIndex].Start();
}
This is my SearchItem() method:
public void searchItem(int start, int pagesToSearchPerThread)
{
for (int count = 0; count < pagesToSearchPerThread; ++count)
{
start++;
for (int activeListCount = 0; activeListCount < this.activeListItems.Count; ++activeListCount)
{
//further method calls here to webservers..
}
}
}
I know about using some shared sentinel to determine when to stop a thread, but I fail to comprehend how to apply it here? How should I be handling this scenario, such that a thread aborts gracefully, when its task is completed...