Based on apomene's solution I'd opt for a (real) timer based solution, since Thread.Sleep
is pretty imprecise.
static void PrintSlowly(string print)
{
int index = 0;
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 100;
timer.Elapsed += new System.Timers.ElapsedEventHandler((sender, args) =>
{
if (index < print.Length)
{
Console.Write(print[index]);
index++;
}
else
{
Console.Write("\n");
timer.Enabled = false;
}
});
timer.Enabled = true;
}
The Timer will come back every 100 milliseconds, pick the next character and print it. If no more characters are available, it prints return and disables itself. I wrote it using an anonymous handling method using a lambda-expression - not the cleanest way. It's just about the principle.
This implementation runs complete in parallel to your application, so it does not block your code-execution. If you want that, a different approach may be better.
Alternatively - as a modification of apomene's solution without busy-wait - you can use a ManualResetEvent
.
static System.Timers.Timer delay = new System.Timers.Timer();
static AutoResetEvent reset = new AutoResetEvent(false);
private static void InitTimer()
{
delay.Interval = 100;
delay.Elapsed += OnTimedEvent;
delay.Enabled = false;
}
private static void OnTimedEvent(object sender, ElapsedEventArgs e)
{
((System.Timers.Timer)sender).Enabled = false;
reset.Set();
}
static void PrintSlowly2(string print)
{
InitTimer();
foreach (char l in print)
{
Console.Write(l);
delay.Enabled = true;
reset.WaitOne();
}
Console.Write("\n");
}
It waits using a AutoResetEvent, so other applications/threads can use the processor!