C# .NET - Buffer messages w/Timer - c#

I need to implement a message buffering system that is also timed based.
What I need to do is store instances of my class and then send them forward either when I reach 100 instances or when 1 minute has passed.
Basically:
List<Message> messages;
public void GotNewMessage(Message msg)
{
messages.add(msg);
if (messages.count() == 100 || timer.elapsed(1 minute))
{
SendMessages(messages);
messages.clear()
}
}
I just can't seem to figure out how to implement this without an excessive use of locks which will slow down the process considerably. Does anyone know of a good way to implement such a system? Thanks in advance.

There is a fantastic library for these kind of requirements (combine time with sequences), it is Reactive Extensions. See https://github.com/Reactive-Extensions/Rx.NET
You could then write something like
void Main()
{
messages
.Buffer(TimeSpan.FromMinutes(1), 100) // Buffer until 100 items or 1 minute has elapsed, whatever comes first.
.Subscribe(msgs => SendMessages(msgs));
}
Subject<Message> messages = new Subject<Message>();
public void GotNewMessage(Message msg)
{
messages.OnNext(msg);
}
Note: this is not production ready but it shows the basic of how to do it. Depending on where you het the messages from there are better ways to create an Observable to subscribe to.
More references:
http://www.introtorx.com/
https://msdn.microsoft.com/en-us/library/hh242985(v=vs.103).aspx
If your message are received using an event you can link the event to a RX stream, see https://msdn.microsoft.com/en-us/library/hh242978(v=vs.103).aspx and https://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.fromeventpattern(v=vs.103).aspx

First of all, you should consider using a ConcurrentQueue<> insted of a List<>. ConcurrentQueue<> is all the way thread safe and needs no additional locks. With this, you have already spared yourself a lock for the message queue.
Interlocked provides atomicity, when it's not available.
According to the C# language specification, independent reads/writes are atomic (but only for some data types and long is not always atomic - that's why I shifted the DateTime.Now.Ticks to get an int32 without losing any bits that would influence the elapsed time) and read-modify-write (eg. ++i) is never atomic.
Shifting (eg. <<) is on its own atomic and doesn't need any additional locking.
private ConcurrentQueue<Message> Queue = new ConcurrentQueue<Message>();
private int QueueSize = 0;
private int LastSend = (int)(DateTime.Now.Ticks >> 23);
private int LastMessage = (int)(DateTime.Now.Ticks >> 23);
public void GotNewMessage(Message Message)
{
Queue.Enqueue(Message);
Interlocked.Increment(ref QueueSize);
Interlocked.Exchange(ref LastMessage, (int)(DateTime.Now.Ticks >> 23));
if (Interlocked.CompareExchange(ref QueueSize, 0, 100) >= 100 ||
LastMessage - LastSend >= 60)
{
Message Dummy;
while (!Queue.IsEmpty)
if (Queue.TryDequeue(out Dummy))
SendMessage(Dummy);
Interlocked.Exchange(ref LastSend, (int)(DateTime.Now.Ticks >> 23));
}
}
public void SendMessage(Message Message)
{
// ...
}
Edit: It may occur, that more than 100 messages are sent out. If you wish to send out strictly 100 messages, you can implement an another atomic incrementation in the cycle.

Related

What is the correct way to use USBHIDDRIVER for multiple writes?

I am writing an application that needs to write messages to a USB HID device and read responses. For this purpose, I'm using USBHIDDRIVER.dll (https://www.leitner-fischer.com/2007/08/03/hid-usb-driver-library/ )
Now it works fine when writing many of the message types - i.e. short ones.
However, there is one type of message where I have to write a .hex file containing about 70,000 lines. The protocol requires that each line needs to be written individually and sent in a packet containing other information (start, end byte, checksum)
However I'm encountering problems with this.
I've tried something like this:
private byte[] _responseBytes;
private ManualResetEvent _readComplete;
public byte[][] WriteMessage(byte[][] message)
{
byte[][] devResponse = new List<byte[]>();
_readComplete = new ManualResetEvent(false);
for (int i = 0; i < message.Length; i++)
{
var usbHid = new USBInterface("myvid", "mypid");
usbHid.Connect();
usbHid.enableUsbBufferEvent(UsbHidReadEvent);
if (!usbHid.write(message)) {
throw new Exception ("Write Failed");
}
usbHid.startRead();
if (!_readComplete.WaitOne(10000)) {
usbHid.stopRead();
throw new Exception ("Timeout waiting for read");
}
usbHid.stopRead();
_readComplete.Reset();
devResponse.Add(_responseBytes.ToArray());
usbHid = null;
}
return devResponse;
}
private void ReadEvent()
{
if (_readComplete!= null)
{
_readComplete.Set();
}
_microHidReadBytes = (byte[])((ListWithEvent)sender)[0];
}
This appears to work. In WireShark I can see the messages going back and forth. However as you can see it's creating an instance of the USBInterface class every iteration. This seems very clunky and I can see in the TaskManager, it starts to eat up a lot of memory - current run has it above 1GB and eventually it falls over with an OutOfMemory exception. It is also very slow. Current run is not complete after about 15 mins, although I've seen another application do the same job in less than one minute.
However, if I move the creation and connection of the USBInterface out of the loop as in...
var usbHid = new USBInterface("myvid", "mypid");
usbHid.Connect();
usbHid.enableUsbBufferEvent(UsbHidReadEvent);
for (int i = 0; i < message.Length; i++)
{
if (!usbHid.write(message)) {
throw new Exception ("Write Failed");
}
usbHid.startRead();
if (!_readComplete.WaitOne(10000)) {
usbHid.stopRead();
throw new Exception ("Timeout waiting for read");
}
usbHid.stopRead();
_readComplete.Reset();
devResponse.Add(_responseBytes.ToArray());
}
usbHid = null;
... now what happens is it only allows me to do one write! I write the data, read the response and when it comes around the loop to write the second message, the application just hangs in the write() function and never returns. (Doesn't even time out)
What is the correct way to do this kind of thing?
(BTW I know it's adding a lot of data to that devResponse object but this is not the source of the issue - if I remove it, it still consumes an awful lot of memory)
UPDATE
I've found that if I don't enable reading, I can do multiple writes without having to create a new USBInterface1 object with each iteration. This is an improvement but I'd still like to be able to read each response. (I can see they are still sent down in Wireshark)

How is such IndexOutOfRangeException possible when debugger shows the index is not out of range?

This is the weirdest runtime error I ever got in C#:
a)
b)
This is ONE BREAKPOINT.
You can see the Messages array has the length of 128.
You can see AT THE SAME TIME the requested array index is 3 (or 2, I'm not sure if the index was incremented or not, but it should not matter here, index 3, length 128, so 0, 1, 2, 3 ... 127 should all be valid indices).
How is the method called? A WebSocket client listens to messages. The messages are written to a circular buffer. The buffer is constant. Preallocated at the session start. So after offset 127 there is offset 0 and so on. It is important that the application should see the latest 127 messages so it can search for interesting stuff. This is a workaround for malformed content sent by the server. The server sends the message in wrong order. Let's say it sends state and updates. But in reverse order. First I get updates, then the state to which the updates are for. With that little trick it works. For hours and hours. And once upon a time my app dies. Being patient and leaving the app for a few hours under VS debugger I got this error. W T F ? !
BTW, there is no concurrency here. There is only ONE session running in the process. The function as you can see is synchronous. There is one thread that reads the messages from the WS server.
There are other threads that communicate to the clients what happens on the remote server, but it seems like the remote server reader have crashed. But what did just happen? The array is 128 items long. All the time. Created over an hour before the crash. The index is 2 or 3 - so within the valid range.
The only explanation I can think of the VS debugger lies to me. Something else have crashed and the debugger shows me wrong part of the code. What now? How would you proceed to debug that stuff furtner?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Woof.Crypto {
class MessageBuffer {
public int Capacity { get; }
public long CurrentId { get; private set; }
public MessageBuffer(int capacity = 128) {
Messages = new (long, object)[Capacity = capacity];
}
public void Write(object message) {
Messages[CurrentOffset++] = (CurrentId++, message);
if (CurrentOffset >= Capacity) CurrentOffset = 0;
}
public IEnumerable<object> GetFromId(long id) => Messages.Where(i => i.Item1 > id).OrderBy(i => i.Item1).Select(i => i.Item2);
readonly (long, object)[] Messages;
int CurrentOffset;
}
}
I know you said this isn't multithreaded, but it has "race" written all over it. If you do have multithreaded access:
It's expected that you'd only get an error randomly, after a long period.
You can get the crash you're seeing, as two threads run Messages[CurrentOffset++] before one of them has a chance to run if (CurrentOffset >= Capacity) CurrentOffset = 0;
The debugger would probably show that CurrentOffset has a small value, as it takes the debugger a little while to break, in which time another thread did manage to reset CurrentOffset to 0, and then increment it.
I recommend doing something like this:
private readonly object lockObject = new object();
public void Write(object message) {
if (!Montor.TryEnter(lockObject))
throw new Exception("We have a race!");
Messages[CurrentOffset++] = (CurrentId++, message);
if (CurrentOffset >= Capacity) CurrentOffset = 0;
Monitor.Exit(lockObject);
}
My money's on that throwing the exception soonish, and you won't see your original crash.
(Note that I haven't followed best practice here: I'm not using TryEnter(object, ref bool) and I'm not using a try/finally. They don't matter for this particular little bit of debugging.)
You can also stick a Thread.Sleep in there if you want to try and trigger the race sooner. You can also try decreasing the size of Messages to a small value, such as 1 or 2, to try and trigger your original exception sooner.

UART communication bug in STM32 and a C# app

Kindly bear with me for this confusing question. I'm finding it as hard to describe as it is involving and tiresome. Read it and you'll know why.
I've been hounding this issue for over a month now without much progress. I'm using an STM32 (STM32F103C8 mounted on a BluePill board) to communicate with a C# app through an FT232r Serial-USB converter. The complete communication protocol is a bit complex. I'm writing here a simplistic version of the code that explains my problem quite accurately.
STM32 does the following.
In the initial setup,
Serial.begin at 2000000 (Yes it's very high but I've analyzed it using an oscilloscope and the signal is very healthy; impedance matching and clock jitter is very accurate).
Waits for a command from the C# end to enter the loop
In the loop, it does the following.
TX a byte buffer of length N on the serial port. Packet structure is 0xAA, N bytes, 1 byte checksum.
repeat the loop
And on the C# side (Pseudo code),
new Thread(()=>{while(true) IOTick(); Thread.Sleep(30); }).Start();
IOTick() is defined as:
{
while(SerialPortObject.BytesToRead > 1)
{
header = read();
if (header != 0xAA) continue;
byte [] buffer = new byte[N + 1];
receivedBytes = readBytes(buffer, N + 1, Timeout = 500ms); // receivedBytes is never less than N + 1 for timeout greater than 120)
use the N=16 bytes. Check Nth byte to compare checksum. Doen't take too much CPU time.
Send a packet received software event.
}
}
readBytes is defined as
int readBytes(byte[] buffer, int count, int timeout)
{
var st = DateTime.Now;
for (int i = 0; i < count; i++)
{
var b_ = read(timeout);
if (b_ == -1)
return i;
buffer[i] = (byte)b_;
timeout -= (int)(DateTime.Now - st).TotalMilliseconds;
}
return count;
}
int buffer2ReadIndex = 0;
byte[] buffer2= new byte[0];
int read(int timeout)
{
DateTime start = DateTime.Now;
if (buffer2.Length == 0)
{
while (SerialPortObject.BytesToRead <= 0)
{
if ((DateTime.Now - start).TotalMilliseconds > timeout)
return -1;
System.Threading.Thread.Sleep(30);
}
buffer2 = new byte[SerialPortObject.BytesToRead];
sp.Read(buffer2, 0, buffer2.Length);
}
if (buffer2.Length > 0)
{
var b = buffer2[buffer2ReadIndex];
buffer2ReadIndex++;
if (buffer2ReadIndex >= buffer2.Length)
{
buffer2ReadIndex = 0;
buffer2 = new byte[0];
}
return b;
}
return -1;
}
Now, everything is working as expected. The packet received software event is triggered not later than every ~30ms (the windows tick time). The problem starts if I have to wait between each packet TX at the STM side. First, I suspected that the I2C I was using for some tasks between each packet TX was causing some HW or software conflict with serial data which gets corrupted. But then I noticed that only if I introduce a delay of 1 millisecond using Arduino delay() between each packet TX, the same thing happens. Almost, 1K packets should be received every second now. Almost 1 out of 10 packets after a successful header exception get either not delivered completely or delivered with corrupted checksum, causing the C# app to lose the packet Header. The new header trace obviously requires flushing some bytes, losing some packets in the communication. Even this doesn't sound too bad for an app that can afford 5% data packet loss, strangely though, when this anomaly occurs, the packet received software interrupt waits for more than 1 second after every couple hundred of consecutive events.
I'm completely blind here. Even tried it with 115200 baud rate, does the same loss with a slightly lesser loss ratio. It should be noted that at 9600 baud, the issue doesn't happen. This is the only hint I've got right now.
It looks like I've found an answer.
After digging deep into SerialPort and SerialPort.base stream class and after doing some document reading and benchmarking, here is what I've observed:
SerialPort.BytesToRead updates are not uniform. DataReceived event seems to be following it. When bytes are coming at ~200kHz, (baud = 2Mbps), It is updated almost instantaneously (or within 30ms, worst case). When they are coming at ~20kHz or slower (evenly spaced on time using a micrcontroller), the SerialPort.BytesToRead can take up to 400ms to update. This happens only after a dozen 30ms updates.
So, observing this, I can say that SerialPort.BytesToRead is updated on two conditions. Some amount of time has passed since the data arrived (and this time is not constrained to 30ms) or the data is coming too fast.
This is a strange behavior. No data is lost when this anomaly is occurring. Not to surprise, 0.06% of bytes are lost when working at full bandwidth (200KBps at baud of 2Mbps).

c# while loop usage

I have a fairly general c# while loop question.
This code should continue to execute only after the RDP session has truly disconnected.
When the Connected property is changed to 0 it means that the RDP session connection has truly terminated. When the property is 1 it is still connected and the connection has not yet terminated.
Does anyone see anything inherently bad about this code? Is there a better way to go about it?
private void Reconnect()
{
rdp1.Disconnect(); // force the RDP session to disconnect
while (rdp1.Connected == 1) // true as long as RDP is still connected
{
// do nothing
}
rdp1.Connect(); // execute this code after while loop is broken
}
/**************************************************************/
Here's the final code I used per James' answer.
The counter suffices as the timeout for my purpose.
int i = 0;
rdp1.Disconnect();
while (rdp1.Connected == 1)
{
if (i == 1000 * 10) break;
else Thread.Sleep(100);
i++;
}
rdp1.Connect();
You should do something in the body of loop, or it will consume all your CPU (at least for one core). Usually in this type of loop, you'd sleep for a while using System.Threading.Thread.Sleep(100) or something. Sleep takes the number of milliseconds to wait before checking the while condition again. Ideally, the RDP object would have a mutex or event or something you could just block on until it was disconnected, but it wouldn't surprise me if they left that out.
EDIT: As Ben pointed out, it's always a good idea to have a way out of the loop as well. Something like this (your stated answer will depend on the CPU speed, which could break in the future when CPUs are much faster):
DateTime stop = DateTime.UtcNow.AddSeconds(30);
while (rdp1.Connected)
{
if (DateTime.UtcNow > stop) throw new ApplicationException ("RDP disconnect timeout!");
System.Threading.Thread.Sleep (100);
}
Of course you will probably want to specify the timeout with a constant, a readonly TimeSpan, or a dynamically configurable TimeSpan rather than a magic number, and you should probably have a specific exception class for this case.
Set a timeout for the purpose
private void Reconnect()
{
timeOut = false;
new System.Threading.Thread(new System.Threading.ThreadStart(setTimeout)).Start();
rdp1.Disconnect();
while (rdp1.Connected == 1 && !timeOut);
rdp1.Connect();
}
bool timeOut = false;
void setTimeout()
{
System.Threading.Thread.Sleep(7000);
timeOut = true;
}

Console.WriteLine slow

I run through millions of records and sometimes I have to debug using Console.WriteLine to see what is going on.
However, Console.WriteLine is very slow, considerably slower than writing to a file.
BUT it is very convenient - does anyone know of a way to speed it up?
If it is just for debugging purposes you should use Debug.WriteLine instead. This will most likely be a bit faster than using Console.WriteLine.
Example
Debug.WriteLine("There was an error processing the data.");
You can use the OutputDebugString API function to send a string to the debugger. It doesn't wait for anything to redraw and this is probably the fastest thing you can get without digging into the low-level stuff too much.
The text you give to this function will go into Visual Studio Output window.
[DllImport("kernel32.dll")]
static extern void OutputDebugString(string lpOutputString);
Then you just call OutputDebugString("Hello world!");
Do something like this:
public static class QueuedConsole
{
private static StringBuilder _sb = new StringBuilder();
private static int _lineCount;
public void WriteLine(string message)
{
_sb.AppendLine(message);
++_lineCount;
if (_lineCount >= 10)
WriteAll();
}
public void WriteAll()
{
Console.WriteLine(_sb.ToString());
_lineCount = 0;
_sb.Clear();
}
}
QueuedConsole.WriteLine("This message will not be written directly, but with nine other entries to increase performance.");
//after your operations, end with write all to get the last lines.
QueuedConsole.WriteAll();
Here is another example: Does Console.WriteLine block?
I recently did a benchmark battery for this on .NET 4.8. The tests included many of the proposals mentioned on this page, including Async and blocking variants of both BCL and custom code, and then most of those both with and without dedicated threading, and finally scaled across power-of-2 buffer sizes.
The fastest method, now used in my own projects, buffers 64K of wide (Unicode) characters at a time from .NET directly to the Win32 function WriteConsoleW without copying or even hard-pinning. Remainders larger than 64K, after filling and flushing one buffer, are also sent directly, and in-situ as well. The approach deliberately bypasses the Stream/TextWriter paradigm so it can (obviously enough) provide .NET text that is already Unicode to a (native) Unicode API without all the superfluous memory copying/shuffling and byte[] array allocations required for first "decoding" to a byte stream.
If there is interest (perhaps because the buffering logic is slightly intricate), I can provide the source for the above; it's only about 80 lines. However, my tests determined that there's a simpler way to get nearly the same performance, and since it doesn't require any Win32 calls, I'll show this latter technique instead.
The following is way faster than Console.Write:
public static class FastConsole
{
static readonly BufferedStream str;
static FastConsole()
{
Console.OutputEncoding = Encoding.Unicode; // crucial
// avoid special "ShadowBuffer" for hard-coded size 0x14000 in 'BufferedStream'
str = new BufferedStream(Console.OpenStandardOutput(), 0x15000);
}
public static void WriteLine(String s) => Write(s + "\r\n");
public static void Write(String s)
{
// avoid endless 'GetByteCount' dithering in 'Encoding.Unicode.GetBytes(s)'
var rgb = new byte[s.Length << 1];
Encoding.Unicode.GetBytes(s, 0, s.Length, rgb, 0);
lock (str) // (optional, can omit if appropriate)
str.Write(rgb, 0, rgb.Length);
}
public static void Flush() { lock (str) str.Flush(); }
};
Note that this is a buffered writer, so you must call Flush() when you have no more text to write.
I should also mention that, as shown, technically this code assumes 16-bit Unicode (UCS-2, as opposed to UTF-16) and thus won't properly handle 4-byte escape surrogates for characters beyond the Basic Multilingual Plane. The point hardly seems important given the more extreme limitations on console text display in general, but could perhaps still matter for piping/redirection.
Usage:
FastConsole.WriteLine("hello world.");
// etc...
FastConsole.Flush();
On my machine, this gets about 77,000 lines/second (mixed-length) versus only 5,200 lines/sec under identical conditions for normal Console.WriteLine. That's a factor of almost 15x speedup.
These are controlled comparison results only; note that absolute measurements of console output performance are highly variable, depending on the console window settings and runtime conditions, including size, layout, fonts, DWM clipping, etc.
Why Console is slow:
Console output is actually an IO stream that's managed by your operating system. Most IO classes (like FileStream) have async methods but the Console class was never updated so it always blocks the thread when writing.
Console.WriteLine is backed by SyncTextWriter which uses a global lock to prevent multiple threads from writing partial lines. This is a major bottleneck that forces all threads to wait for each other to finish the write.
If the console window is visible on screen then there can be significant slowdown because the window needs to be redrawn before the console output is considered flushed.
Solutions:
Wrap the Console stream with a StreamWriter and then use async methods:
var sw = new StreamWriter(Console.OpenStandardOutput());
await sw.WriteLineAsync("...");
You can also set a larger buffer if you need to use sync methods. The call will occasionally block when the buffer gets full and is flushed to the stream.
// set a buffer size
var sw = new StreamWriter(Console.OpenStandardOutput(), Encoding.UTF8, 8192);
// this write call will block when buffer is full
sw.Write("...")
If you want the fastest writes though, you'll need to make your own buffer class that writes to memory and flushes to the console asynchronously in the background using a single thread without locking. The new Channel<T> class in .NET Core 2.1 makes this simple and fast. Plenty of other questions showing that code but comment if you need tips.
A little old thread and maybe not exactly what the OP is looking for, but I ran into the same question recently, when processing audio data in real time.
I compared Console.WriteLine to Debug.WriteLine with this code and used DebugView as a dos box alternative. It's only an executable (nothing to install) and can be customized in very neat ways (filters & colors!). It has no problems with tens of thousands of lines and manages the memory quite well (I could not find any kind of leak, even after days of logging).
After doing some testing in different environments (e.g.: virtual machine, IDE, background processes running, etc) I made the following observations:
Debug is almost always faster
For small bursts of lines (<1000), it's about 10 times faster
For larger chunks it seems to converge to about 3x
If the Debug output goes to the IDE, Console is faster :-)
If DebugView is not running, Debug gets even faster
For really large amounts of consecutive outputs (>10000), Debug gets slower and Console stays constant. I presume this is due to the memory, Debug has to allocate and Console does not.
Obviously, it makes a difference if DebugView is actually "in-view" or not, as the many gui updates have a significant impact on the overall performance of the system, while Console simply hangs, if visible or not. But it's hard to put numbers on that one...
I did not try multiple threads writing to the Console, as I think this should generally avoided. I never had (performance) problems when writing to Debug from multiple threads.
If you compile with Release settings, usually all Debug statements are omitted and Trace should produce the same behaviour as Debug.
I used VS2017 & .Net 4.6.1
Sorry for so much code, but I had to tweak it quite a lot to actually measure what I wanted to. If you can spot any problems with the code (biases, etc.), please comment. I would love to get more precise data for real life systems.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
namespace Console_vs_Debug {
class Program {
class Trial {
public string name;
public Action console;
public Action debug;
public List < float > consoleMeasuredTimes = new List < float > ();
public List < float > debugMeasuredTimes = new List < float > ();
}
static Stopwatch sw = new Stopwatch();
private static int repeatLoop = 1000;
private static int iterations = 2;
private static int dummy = 0;
static void Main(string[] args) {
if (args.Length == 2) {
repeatLoop = int.Parse(args[0]);
iterations = int.Parse(args[1]);
}
// do some dummy work
for (int i = 0; i < 100; i++) {
Console.WriteLine("-");
Debug.WriteLine("-");
}
for (int i = 0; i < iterations; i++) {
foreach(Trial trial in trials) {
Thread.Sleep(50);
sw.Restart();
for (int r = 0; r < repeatLoop; r++)
trial.console();
sw.Stop();
trial.consoleMeasuredTimes.Add(sw.ElapsedMilliseconds);
Thread.Sleep(1);
sw.Restart();
for (int r = 0; r < repeatLoop; r++)
trial.debug();
sw.Stop();
trial.debugMeasuredTimes.Add(sw.ElapsedMilliseconds);
}
}
Console.WriteLine("---\r\n");
foreach(Trial trial in trials) {
var consoleAverage = trial.consoleMeasuredTimes.Average();
var debugAverage = trial.debugMeasuredTimes.Average();
Console.WriteLine(trial.name);
Console.WriteLine($ " console: {consoleAverage,11:F4}");
Console.WriteLine($ " debug: {debugAverage,11:F4}");
Console.WriteLine($ "{consoleAverage / debugAverage,32:F2} (console/debug)");
Console.WriteLine();
}
Console.WriteLine("all measurements are in milliseconds");
Console.WriteLine("anykey");
Console.ReadKey();
}
private static List < Trial > trials = new List < Trial > {
new Trial {
name = "constant",
console = delegate {
Console.WriteLine("A static and constant string");
},
debug = delegate {
Debug.WriteLine("A static and constant string");
}
},
new Trial {
name = "dynamic",
console = delegate {
Console.WriteLine("A dynamically built string (number " + dummy++ + ")");
},
debug = delegate {
Debug.WriteLine("A dynamically built string (number " + dummy++ + ")");
}
},
new Trial {
name = "interpolated",
console = delegate {
Console.WriteLine($ "An interpolated string (number {dummy++,6})");
},
debug = delegate {
Debug.WriteLine($ "An interpolated string (number {dummy++,6})");
}
}
};
}
}
Just a little trick I use sometimes: If you remove focus from the Console window by opening another window over it, and leave it until it completes, it won't redraw the window until you refocus, speeding it up significantly. Just make sure you have the buffer set up high enough that you can scroll back through all of the output.
Try using the System.Diagnostics Debug class? You can accomplish the same things as using Console.WriteLine.
You can view the available class methods here.

Categories