C# using LoadFile or ReadallLines on RichTextBox - c#

I have a problem on a few systems that when we are trying to load the RichTextBox the program becomes unresponsive, we cannot do anything and will have to kill it via Taskmanager.
its working on most systems but a few systems located in a different country there seems to be problem.
we have tried something as simple as :
private void testing4()
{
richTextBox1.LoadFile(#"C:\testing.logs", RichTextBoxStreamType.PlainText);
}
If we decide to use a normal TextBox it appears to be working using .net 4.5, but it still becomes unresponsive. Any ideas?

This may help you:
foreach(var line in File.ReadLines(#"C:\testing.logs"))
{
richTextBox1.AppendText(line+Environment.NewLine);
}

Since you are using framework 4.5, you can do it async, as in MSDN example:
public async void ReadFile()
{
string filePath = #"C:\testing.logs";
if (File.Exists(filePath) == false)
{
Debug.WriteLine("file not found: " + filePath);
}
else
{
try
{
string text = await ReadTextAsync(filePath);
richTextBox1.AppendText(text);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
private async Task<string> ReadTextAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
Source: Using Async for File Access

Related

Task.Run still freezing UI

So, i'm trying to convert a large byte array into it's base64 encoded variant. But no matter what i try, it seems to freeze up my UI every time it runs.
This is what i've got currently:
private async void TxtOutput_DragDrop(object sender, DragEventArgs e)
{
string outputText = String.Empty;
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] path = (string[])e.Data.GetData(DataFormats.FileDrop);
byte[] fileBytes = File.ReadAllBytes(path[0]);
txtOutput.Text = await Task.Run(() => {return Convert.ToBase64String(fileBytes);});
_ = fileBytes;
_ = path;
}
}
So, the line that freezes everything up is:
txtOutput.Text = await Task.Run(() => {return Convert.ToBase64String(fileBytes);});
File.ReadAllBytes(path[0])
Could be a bottle neck you can use async operation for read files
Here is an example how to read file async
public async Task ProcessReadAsync()
{
string filePath = #"temp2.txt";
if (File.Exists(filePath) == false)
{
Debug.WriteLine("file not found: " + filePath);
}
else
{
try
{
string text = await ReadTextAsync(filePath);
Debug.WriteLine(text);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
private async Task<string> ReadTextAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
Right, so it turns out that my problem was using a textbox for writing the string to instead of a richtextbox. This fixed my problem. Thanks for your answers.

Asynchronous Programming in C# with Tasks [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I started to learn about async programming and I stumbled across this problem. I call these functions over an Dispatcher.BeginInvoke.
I'm expecting to get file content form ReadText method, but all I get back is "System.Threading.Tasks.Task`1[System.String]"
So question is what's wrong with my code and which line should I fix?
Sadly I can't figure out where my problem is because I am looking at this peace of code for quite some time now.
I thought because I get back the time of the object and not the object itself that my ReadText method is wrong, but I don't see where. It seems there is something wrong with my part below the Stringbuilder or the way I made these methods async.
If you wonder why I used two methods is to get known with await and calling async Task methods. I also tried making the method a Tast method but that only resulted in even more problems.
Thanks for your help in advance.
public async void ReadFile()
{
string filePath = #"SampleFile.txt";
if (File.Exists(filePath) == false)
{
MessageBox.Show(filePath + " not found", "File Error", MessageBoxButton.OK);
}
else
{
try
{
string text = await ReadText(filePath);
txtContents.Text = text;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
private async Task<string> ReadText(string filePath)
{
Task Readfile = Task.Run(() =>
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = sourceStream.Read(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
);
await Readfile;
return Readfile.ToString();
}
You are returning a string, so make Readfile a Task<string>:
Task<string> Readfile = Task.Run<string>( ... )
Then you want to return Readfile.Result;, not Readfile.ToString();
But you can write this simpler:
return await Readfile;
or even:
return await Task.Run<string>( ... )
You don't need to use Task.Run for reading from the stream, there is convenient method ReadAsync that you can await:
public async Task ReadFile() {
string filePath = #"SampleFile.txt";
if (File.Exists(filePath) == false) {
MessageBox.Show(filePath + " not found", "File Error", MessageBoxButton.OK);
} else {
try {
string text = await ReadText(filePath);
txtContents.Text = text;
} catch (Exception ex) {
Debug.WriteLine(ex.Message);
}
}
}
private async Task<string> ReadText(string filePath) {
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true)) {
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0) {
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
Also avoid async void is not recommended, try to avoid that.Async void methods have different error-handling semantics. When an exception is thrown out of an async Task or async Task method, that exception is captured and placed on the Task object. With async void methods, there is no Task object, so any exceptions thrown out of an async void method will be raised directly on the SynchronizationContext that was active when the async void method started.
Best practice for async methods

Async Task outputting in chinese characters instead of readable text

I am attempting to search files for specific text using an async Task. The output I receive is in chinese characters instead of what is actually in the text file I am parsing. Here is the code:
public async void ProcessRead(string fileLocation)
{
string filePath = fileLocation;
if (File.Exists(filePath) == false)
{
Debug.WriteLine("file not found: " + filePath);
}
else
{
try
{
string text = await ReadTextAsync(filePath);
Debug.WriteLine(text);
if (text.Contains(inputContentPattern))
{
addToDataGrid(Path.GetFileName(filePath), filePath, "");
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
findButton.Enabled = true;
cancelFindButton.Enabled = false;
}
private async Task<string> ReadTextAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
You are reading the file using Unicode encoding (in an incorrect way). Find out what encoding the file actually has and use that encoding. Simply use File.ReadAllText and delete ReadTextAsync.
Async IO brings you zero performance benefits here so just don't do it. If this is a UI app use await Task.Run(() => File.ReadAllText(...)).

How to check whether my C# code is reading the file in asynchronous mode?

public void fileReader()
{
Stream stream = new FileStream(filename, FileMode.Open , FileAccess.Read , FileShare.None, 30, true);
byte[] Buffer = new byte[30];
while (stream.Read(Buffer, 0, 30) > 0)
{
label1.text=Encoding.UTF8.GetString(Buffer);
Thread.Sleep(1000);
}
stream.Dispose();
}
THIS IS MY C# CODE TO READ 30 BYTES OF DATA AT A TIME FROM A FILE. I've created the Stream with FileStream constructor having useAsync=true. Here stream.Read method is used.
Is this read operation working in ASYNCHRNOUS mode?
How to check this?
Another problem is that Encoding.UTF8.GetString(Buffer); gives white spaces as '□' character... y?
Is there any other way to make a 1 second delay other than Thread.Sleep(1000); ?
It doesn't since you are using the syncronous Readmethod
if you wish to read it asyncronous you would have to use the BeginRead method
Below is an example on the usage of BeginRead from MSDN
private void ReadStreamAsyncImpl(Stream stream)
{
chunk = new byte[chunkSize];
stream.BeginRead(chunk,
0,
chunkSize,
new AsyncCallback(BeginReadCallback),
stream);
}
private void BeginReadCallback(IAsyncResult ar)
{
Stream stream = ar.AsyncState as Stream;
int bytesRead = stream.EndRead(ar);
StreamContentsAsString += StreamEncoding.GetString(chunk, 0, bytesRead);
if (bytesRead < chunkSize) {
// Finished
isOperationInProgress = false;
stream.Close();
if (null != ReadStreamCompleted) {
ReadStreamCompleted(this, new EventArgs());
}
} else {
ReadStreamAsyncImpl(stream);
}
}
That said you should probably use a StreamReader to read the characters of the stream instead of converting them yourself.
if you are using .NET 4.5 you can use ReadAsync as below (again from [MSDN][2])
private async void Button_Click(object sender, RoutedEventArgs e)
{
UnicodeEncoding uniencoding = new UnicodeEncoding();
string filename = #"c:\Users\exampleuser\Documents\userinputlog.txt";
byte[] result;
using (FileStream SourceStream = File.Open(filename, FileMode.Open))
{
result = new byte[SourceStream.Length];
await SourceStream.ReadAsync(result, 0, (int)SourceStream.Length);
}
UserInput.Text = uniencoding.GetString(result);
}
Reading your file like that seems to be causing you a lot of problems without solving anything. I do not see the point of reading 30 bytes at a time and then decode the result. You might end up decoding the last character wrong.
I recommend that you do something like this:
using(StreamReader reader = new StreamReader(filename, Encoding.UTF8))
{
while(!reader.EndOfStream)
{
String result = await reader.ReadLineAsync();
label1.Text = result;
}
}
But maybe a BackgroundWorker is much easier to use, sending the line to the UI using the progress callback.
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
using(StreamReader reader = new StreamReader(e.Argument as String, Encoding.UTF8))
{
while(!reader.EndOfStream)
{
String line = reader.ReadLine();
backgroundWorker.ReportProgress(0, line);
Thread.Sleep(1000);
if (backgroundWorker.CancellationPending)
return;
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.UserState as String;
}

FileStream and ObjectDisposedException in .NET CF

public byte[] GetFile(string filename)
{
FileStream aStream = File.Open(filename, FileMode.Open, FileAccess.Read);
BinaryReader binReader = new BinaryReader(aStream);
binReader.BaseStream.Position = 0;
byte[] binFile = binReader.ReadBytes(Convert.ToInt32(binReader.BaseStream.Length));
binReader.Close();
return binFile;
}
I run this method for a number of filepaths, problem is whenever a file cannot be accessed with File.Open (because it is used by another process) I get:
'aStream.Position' threw an exception of type 'System.ObjectDisposedException'
on the following line:
binReader.BaseStream.Position = 0;
And seldom I get
{System.IO.IOException: The process can not access the file '\folder\file.txt' because it is being used by another process.}
This is the exception I want. So why is the object disposed most of the times?
Note: I first had the FileStream line in a using statement but removed it because I thought that might have disposed the object. But the problem remains.
Edit: Using Compact Framework, which doesn't have ReadAllBytes.
Maybe that part of the time your FileStream is throwing the IOException whenever your file is in use, and at other times, perhaps, you are getting the ObjectDisposedException because your array is not initialized.
Obviously, I can not test this theory.
See if you can copy-n-paste this one with good results:
public byte[] GetFile(string filename)
{
byte[] binFile = null;
try
{
using (var aStream = File.Open(filename, FileMode.Open, FileAccess.Read))
{
BinaryReader binReader = new BinaryReader(aStream);
binFile = new byte[binReader.BaseStream.Length];
binReader.BaseStream.Position = 0; // <= this step should not be necessary
binFile = binReader.ReadBytes(binReader.BaseStream.Length);
binReader.Close();
}
} catch (IOException err) {
// file is being used by another process.
} catch (ObjectDisposedException err) {
// I am guessing you would never see this because your binFile is not disposed
}
return binFile;
}
Be sure to check for null return variables!
EDIT:
I wrote (what I think is) a simpler version. I tested it, and it seems to work OK. I also prefer Read() overload to ReadBytes(), because I know how much data was pulled in.
First, is the test function that calls the method for every image in my Pictures folder:
public void Test() {
DirectoryInfo dir = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
foreach (var subDir in dir.GetDirectories()) {
if (-1 < subDir.Name.ToLower().IndexOf("pictures")) {
foreach (var file in subDir.GetFiles()) {
byte[] data = GetFile(file.FullName);
if (data != null) {
Console.WriteLine(data.Length);
}
}
}
}
}
public byte[] GetFile(string filename) {
byte[] result = null;
try {
if (File.Exists(filename)) {
int len = 0;
FileInfo file = new FileInfo(filename);
byte[] data = new byte[file.Length];
using (BinaryReader br = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read))) {
len = br.Read(data, 0, data.Length);
br.Close();
}
if (0 < len) {
if (len == data.Length) {
return data;
} else {
// this section of code was never triggered in my tests;
// however, it is good to keep it as a backup.
byte[] dat2 = new byte[len];
Array.Copy(data, dat2, len);
return dat2;
}
}
}
} catch (IOException err) {
// file is being used by another process.
} catch (ObjectDisposedException err) {
// I am guessing you would never see this because your binFile is not disposed
}
return result;
}
I don't see any reason why these would not work - unless you are having an int overflow.
Just use this:
byte[] contents = File.ReadAllBytes(filename);
Why don't you simply use
public byte[] GetFile(string filename)
{
try { return File.ReadAllBytes(filename); }
catch { return null; }
}
Just for fun, you could even define an extension method
public static class Extensions
{
public static byte[] GetFile(this string filename)
{
try { return File.ReadAllBytes(filename); }
catch { return null; }
}
}
so you could do byte[] myfile = filename.GetFile();.
Remember you must check that return is not null before proceed:
if (myfile != null)
{
// Do what you need
}

Categories