Some console applications, such a plink, may not print a new line character after printing important information (eg. "Store key in cache? (y/n)"). Is there a built in way to asynchronously read from a programs stdout that does not wait for new lines? If not, is creating a separate thread to read characters synchronously a good idea?
Just use Read() instead of ReadLine(). A simple asynchronous implementation would look something like this:
void SomeMethod()
{
Process process = ...; // init as appropriate, including redirection of stdout
StringBuilder sb = new StringBuilder();
var _ = ConsumeReader(process.StandardOutput, sb);
}
async Task ConsumeReader(TextReader reader, StringBuilder sb)
{
char[] buffer = new char[1024];
int cch;
while ((cch = await reader.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
sb.Append(buffer, 0, cch);
}
}
The above simply copies the text to a StringBuilder. Presumably in your own scenario you would do something else, like parse it and respond to prompts, that sort of thing. Given the lack of a code example, I can't be more specific than that.
This example also ignores the Task returned from the async method. That may be fine in your case, or you might want to give the variable a better name than _ and eventually wait on the Task at some later point. Use it as you see fit.
Related
I need a serial port program to read data coming in at 4800 baud. Right now I have a simulator sending 15 lines of data every second. The output of it seems to get "behind" and can't keep up with the speed/amount of data coming in.
I have tried using ReadLine() with a DataReceieved event, which did not seem to be reliable, and now I am using an async method with serialPort.BaseStream.ReadAsync:
okToReadPort = true;
Task readTask = new Task(startAsyncRead);
readTask.Start();
//this method starts the async read process and the "nmeaList" is what
// is used by the other thread to display data
public async void startAsyncRead()
{
while (okToReadPort)
{
Task<string> task = ReadLineAsync(serialPort);
string line = await task;
NMEAMsg tempMsg = new NMEAMsg(line);
if (tempMsg.sentenceType != null)
{
nmeaList[tempMsg.sentenceType] = tempMsg;
}
}
public static async Task<string> ReadLineAsync(
this SerialPort serialPort)
{
// Console.WriteLine("Entering ReadLineAsync()...");
byte[] buffer = new byte[1];
string ret = string.Empty;
while (true)
{
await serialPort.BaseStream.ReadAsync(buffer, 0, 1);
ret += serialPort.Encoding.GetString(buffer);
if (ret.EndsWith(serialPort.NewLine))
return ret.Substring(0, ret.Length - serialPort.NewLine.Length);
}
}
This still seems inefficient, does anyone know of a better way to ensure that every piece of data is read from the port and accounted for?
Generally speaking, your issue is that you are performing IO synchronously with data processing. It doesn't help that your data processing is relatively expensive (string concatenation).
To fix the general problem, when you read a byte put it into a processing buffer (BlockingCollection works great here as it solves Producer/Consumer) and have another thread read from the buffer. That way the serial port can immediately begin reading again instead of waiting for your processing to finish.
As a side note, you would likely see a benefit by using StringBuilder in your code instead of string concatenation. You should still process via queue though.
I have the following method:
public static string Sha256Hash(string input) {
if(String.IsNullOrEmpty(input)) return String.Empty;
using(HashAlgorithm algorithm = new SHA256CryptoServiceProvider()) {
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = algorithm.ComputeHash(inputBytes);
return BitConverter.ToString(hashBytes).Replace("-", String.Empty);
}
}
Is there a way to make it asynchronous? I was hoping to use the async and await keywords, but the HashAlgorithm class does not provide any asynchronous support for this.
Another approach was to encapsulate all the logic in a:
public static async string Sha256Hash(string input) {
return await Task.Run(() => {
//Hashing here...
});
}
But this does not seem clean and I'm not sure if it's a correct (or efficient) way to perform an operation asynchronously.
What can I do to accomplish this?
As stated by the other answerers, hashing is a CPU-bound activity so it doesn't have Async methods you can call. You can, however, make your hashing method async by asynchronously reading the file block by block and then hashing the bytes you read from the file. The hashing will be done synchronously but the read will be asynchronous and consequently your entire method will be async.
Here is sample code for achieving the purpose I just described.
public static async Threading.Tasks.Task<string> GetHashAsync<T>(this Stream stream)
where T : HashAlgorithm, new()
{
StringBuilder sb;
using (var algo = new T())
{
var buffer = new byte[8192];
int bytesRead;
// compute the hash on 8KiB blocks
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
algo.TransformBlock(buffer, 0, bytesRead, buffer, 0);
algo.TransformFinalBlock(buffer, 0, bytesRead);
// build the hash string
sb = new StringBuilder(algo.HashSize / 4);
foreach (var b in algo.Hash)
sb.AppendFormat("{0:x2}", b);
}
return sb?.ToString();
}
The function can be invoked as such
using (var stream = System.IO.File.OpenRead(#"C:\path\to\file.txt"))
string sha256 = await stream.GetHashAsync<SHA256CryptoServiceProvider>();
Of course,you could equally call the method with other hash algorithms such as SHA1CryptoServiceProvider or SHA512CryptoServiceProvider as the generic type parameter.
Likewise with a few modifications, you can also get it to hash a string as is specific to your case.
The work that you're doing is inherently synchronous CPU bound work. It's not inherently asynchronous as something like network IO is going to be. If you would like to run some synchronous CPU bound work in another thread and asynchronously wait for it to be completed, then Task.Run is indeed the proper tool to accomplish that, assuming the operation is sufficiently long running to need to perform it asynchronously.
That said, there really isn't any reason to expose an asynchronous wrapper over your synchronous method. It generally makes more sense to just expose the method synchronously, and if a particular caller needs it to run asynchronously in another thread, they can use Task.Run to explicitly indicate that need for that particular invocation.
The overhead of running this asynchronously (using Task.Run) will probably be higher that just running it synchronously.
An asynchronous interface is not available because it is a CPU bound operation. You can make it asynchronous (using Task.Run) as you pointed out, but I would recommend against it.
My wpf application connects to my legacy application through communication pipes. WPF application allows user to plot locations on map using a button on the interface. So when user clicks the button on WPF application user interface, a pipe message is sent to legacy application to allow user to plot locations on map. When user plot locations on map using mouse, the coordinates are sent back to wpf application using the 2 way communication pipe. When my wpf application receives the coordinates, it needs to process and perform the workflows accordingly. There might appear some errors, so application might need to show error message. or in some cases might need to clear collections that were created in Application main thread. So there is a whole branch of code that get executed when coordinates are received.
How can I bring my WPF application back to Main thread so that when coordinates are received, user actions like showing message box etc.. can be performed?
right now I am getting exceptions like "collection was created in a different thread".
I know I can use this code to show message in Main thread or clear collections
Application.Current.Dispatcher.Invoke((Action)(() => { PointsCollection.Clear(); }));
Application.Current.Dispatcher.Invoke((Action)(() => { MessageBox.Show("Error"); }));
but this wont work in unit testing and also I will have to do this in lot of places. is there a better way?
public void PipeClientMessageReceived(int type, string message)
{
var command = (PipeCommand)type;
switch (command)
{
case PipeCommand.Points:
{
string[] tokens = message.Split(':');
var x = Convert.ToDouble(tokens[0]);
var y = Convert.ToDouble(tokens[1]);
SetSlotCoordinates(new Point2D(x, y));
}
break;
}
}
SetSlotCoordinates method actually does all the work to process the coordinates. I tried putting this calling in Application.Current.Dispatcher but no success.
Application.Current.Dispatcher.Invoke((Action)(() => { SetSlotCoordinates(new Point2D(x, y)); }));
Unfortunately, the question is not very clear. What issue exists with unit testing that you believe prevents you from using Dispatcher.Invoke()? When you tried using Dispatcer.Invoke() on the call to SetSlotCoordinates(), in what way was there "no success"?
Basically, the use of Dispatcher.Invoke() (or its asynchronous sibling, Dispatcher.BeginInvoke() should do the job for you. However, if you're able, I would recommend using the new async/await pattern.
Without a complete code example, it's impossible to give you the exact code. But it would look something like this:
async Task ReceiveFromPipe(Stream pipeStream, int bufferSize)
{
byte[] buffer = new byte[bufferSize];
int byteCount;
while ((byteCount = await pipeStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
int type;
string message;
if (TryCompleteMessage(buffer, byteCount, out type, out message))
{
PipeClientMessageReceived(type, message);
}
}
}
Using this technique, and assuming that the ReceiveFromPipe() method is called from the UI thread, you will already be on the UI thread when the read from the pipe completes, making everything else "just work".
Note: I've glossed over details such as how exactly you maintain your buffer of incoming data until a complete message is received...I've assumed that's encapsulated in the hypothetical TryCompleteMessage() method. The above is for illustration purposes, and of course you'd have to adapt to your own specific code.
Also, you may find it makes more sense to do more of the processing in the background thread, in which case you'd put the actual receive and that processing into a separate async method; in that case, that method would still call ReadAsync(), but you could call ConfigureAwait(false) on the return value of that, so that the switch back to the UI thread didn't happen until that separate async method returned. For example:
async Task ReceiveFromPipe(Stream pipeStream, int bufferSize)
{
Action action;
while ((action = await ReceivePoint2D(pipeStream, bufferSize)) != null)
{
action();
}
}
async Task<Action> ReceivePoint2D(Stream pipeStream, int bufferSize)
{
byte[] buffer = new byte[bufferSize];
int byteCount;
while ((byteCount = await pipeStream
.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0)
{
int type;
string message;
if (TryCompleteMessage(buffer, byteCount, out type, out message))
{
return PipeClientMessageReceived(type, message);
}
}
return null;
}
public Action PipeClientMessageReceived(int type, string message)
{
var command = (PipeCommand)type;
switch (command)
{
case PipeCommand.Points:
{
string[] tokens = message.Split(':');
var x = Convert.ToDouble(tokens[0]);
var y = Convert.ToDouble(tokens[1]);
return () => SetSlotCoordinates(new Point2D(x, y));
}
break;
}
}
In the above example, the asynchronous code does everything except the call to SetSlotCoordinates(). For that, it wraps the call in an Action delegate, returning that to the UI thread where the UI thread can then invoke it. Of course, you don't have to return an Action delegate; that was just the most convenient way I saw to adapt the code you already have. You can return any value or object and let the UI thread handle it appropriately.
Finally, with respect to all of the above, note that nowhere in the code is an explicit dependency on the UI thread. While I'm not sure what issue you are concerned with respect to unit testing, the above should be much more easily adapted to unit testing scenarios where no Dispatcher is available or you'd prefer not to use it for some reason.
If you want to stick with explicit use of Dispatcher, then you should be more specific about what exactly isn't working.
I don't quite 'get' async and await yet, and I'm looking for some clarification around a particular problem I'm about to solve. Basically, I need to write some code that'll handle a TCP connection. It'll essentially just receive data and process it until the connection is closed.
I'd normally write this code using the NetworkStream BeginRead and EndRead pattern, but since the async / await pattern is much cleaner, I'm tempted to use that instead. However, since I admittedly don't fully understand exactly what is involved in these, I'm a little wary of the consequences. Will one use more resources than the other; will one use a thread where another would use IOCP, etc.
Convoluted example time. These two do the same thing - count the bytes in a stream:
class StreamCount
{
private Stream str;
private int total = 0;
private byte[] buffer = new byte[1000];
public Task<int> CountBytes(Stream str)
{
this.str = str;
var tcs = new TaskCompletionSource<int>();
Action onComplete = () => tcs.SetResult(total);
str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, onComplete);
return tcs.Task;
}
private void BeginReadCallback(IAsyncResult ar)
{
var bytesRead = str.EndRead(ar);
if (bytesRead == 0)
{
((Action)ar.AsyncState)();
}
else
{
total += bytesRead;
str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, ar.AsyncState);
}
}
}
... And...
public static async Task<int> CountBytes(Stream str)
{
var buffer = new byte[1000];
var total = 0;
while (true)
{
int bytesRead = await str.ReadAsync(buffer, 0, 1000);
if (bytesRead == 0)
{
break;
}
total += bytesRead;
}
return total;
}
To my eyes, the async way looks cleaner, but there is that 'while (true)' loop that my uneducated brain tells me is going to use an extra thread, more resources, and therefore won't scale as well as the other one. But I'm fairly sure that is wrong. Are these doing the same thing in the same way?
To my eyes, the async way looks cleaner, but there is that 'while (true)' loop that my uneducated brain tells me is going to use an extra thread, more resources, and therefore won't scale as well as the other one.
Nope, it won't. The loop will only use a thread when it's actually running code... just as it would in your BeginRead callback. The await expression will return control to whatever the calling code is, having registered a continuation which jumps back to the right place in the method (in an appropriate thread, based on the synchronization context) and then continues running until it either gets to the end of the method or hits another await expression. It's exactly what you want :)
It's worth learning more about how async/await works behind the scenes - you might want to start with the MSDN page on it, as a jumping off point.
I'm just starting out with C#'s new async features. I've read plenty of how-to's now on parallel downloads etc. but nothing on reading/processing a text file.
I had an old script I use to filter a log file and figured I'd have a go at upgrading it. However I'm unsure if my usage of the new async/await syntax is correct.
In my head I see this reading the file line by line and passing it on for processing in different thread so it can continue without waiting for a result.
Am I thinking about it correctly, or what is the best way to implement this?
static async Task<string[]> FilterLogFile(string fileLocation)
{
string line;
List<string> matches = new List<string>();
using(TextReader file = File.OpenText(fileLocation))
{
while((line = await file.ReadLineAsync()) != null)
{
CheckForMatch(line, matches);
}
}
return matches.ToArray();
}
The full script: http://share.linqpad.net/29kgbe.linq
In my head I see this reading the file line by line and passing it on for processing in different thread so it can continue without waiting for a result.
But that's not what your code does. Instead, you will (asynchronously) return an array when all reading is done. If you actually want to asynchronously return the matches one by one, you would need some sort of asynchronous collection. You could use a block from TPL Dataflow for that. For example:
ISourceBlock<string> FilterLogFile(string fileLocation)
{
var block = new BufferBlock<string>();
Task.Run(async () =>
{
string line;
using(TextReader file = File.OpenText(fileLocation))
{
while((line = await file.ReadLineAsync()) != null)
{
var match = GetMatch(line);
if (match != null)
block.Post(match);
}
}
block.Complete();
});
return block;
}
(You would need to add error handling, probably by faulting the returned block.)
You would then link the returned block to another block that will process the results. Or you could read them directly from the block (by using ReceiveAsync()).
But looking at the full code, I'm not sure this approach would be that useful to you. Because of the way you process the results (grouping and then ordering by count in each group), you can't do much with them until you have all of them.