Reputation: 3733
When I am using the scrollbar in the console window all Threads and Tasks are getting paused. Are there any ways to prevent that from happening?
example:
Task.Run(async () =>
{
for (var z = 0; true; z++)
{
Console.WriteLine(z);
await Task.Delay(200);
}
});
or
var s = new Thread(() =>
{
for (var z = 0; true; z++)
{
Console.WriteLine(z);
Thread.Sleep(200);
}
});
If you run either one of these code samples as a console application, both will do the same: print some numbers. During execution hold the scrollbar with your left mouse button for some time and the numbers will stop coming up. The Task/Thread has been paused. When you release the mouse button the numbers will continue.
Because the number after the release of the scroll bar follows the one before, the console has not simply stopped the output of the numbers. It has been waiting in the Console.WriteLine - method until a am releasing the scroll bar.
Does anyone know how to fix my problem?
Upvotes: 4
Views: 1368
Reputation: 203815
You'll need to asynchronously write to the console if you don't want the code to block when access to the console is locked (in this case, by the user), and not wait for that asynchronous operation to finish before continuing on. This can be done as simply as using Task.Run(() => Console.WriteLine(z))
in place of Console.WriteLine(z)
.
You'll also need to make a copy (before the call to Run
) of any closed over variables that will end up being mutated after the call to Task.Run
, since closures close over variables rather than values.
That said, it's a strong indication that you should re-consider your design here. Perhaps the console isn't the right way for you to output your data; another type of UI may be appropriate.
Upvotes: 1
Reputation: 127603
There is not much you can do to stop this. Console.WriteLine
will block while you are holding down your scroll bar, this has nothing to do with threads or tasks at all. The following small program shows the same issue.
using System;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
for (var z = 0; true; z++)
{
Console.WriteLine(z);
Thread.Sleep(200);
}
}
}
}
You can't change the behavior of Console.WriteLine
the only thing you can do is put a buffer between you and the writes to the console.
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//The writer lives in another thread.
var s = new Thread(ConsoleWriter);
s.Start();
for (var z = 0; true; z++)
{
//This add call does not get blocked when Console.WriteLine gets blocked.
LinesToWrite.Add(z.ToString());
Thread.Sleep(200);
}
}
static void ConsoleWriter()
{
foreach (var line in LinesToWrite.GetConsumingEnumerable())
{
//This will get blocked while you hold down the scroll bar but
// when you let go it will quickly catch up.
Console.WriteLine(line);
}
}
static readonly BlockingCollection<string> LinesToWrite = new BlockingCollection<string>();
}
}
This is only a quick and dirty solution to this, there are other ways of solving this to make it more transparent like making a class derived from TextWriter
that will buffer the calls and using that class in a call to Console.SetOut(
.
Upvotes: 3