Await for a process to finish execution - c#

I have a process that takes some varying time to execute. The proceeding part of the code depends on its results.
The process creates a printable file (PRN) file. The proceeding section then reads that file and returns its bytes contents.
When i put a breakpoint at the using statement, i get to read the bytes of the created file and return them to where they are being requested. But when i execute as usual, i get the error.
_ The process cannot access the file 'linkToFile' because it is being used by another process _
lbl.PrintSettings.PrinterName = printerName;
byte[] fileBytes = null;
Task.Run(() => { lbl.Print(int.Parse(qty)); }).Wait(2000);
using (var strm = File.Open(outPutPrintFile,
FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (var ms = new MemoryStream())
{
strm.CopyTo(ms);
fileBytes = ms.ToArray();
}
}
return Ok(fileBytes);
I tried to put the part that executes longer in a Task-Wait part but still getting the same error.

Try using Fileshare.ReadWrite instead of FileShare.Read. It's not for some unknown reason as you commented but ReadWrite make sure that further Read/Write operations can be done on opening the file. From your posted code it looks to be the option to choose.

Related

can i make Multiple FileStream objects to one file in the same time?

why in fs2 object throw error ?? i already have written a FileShare.ReadWrite in fs object
FileStream fs = new FileStream("hello.txt",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
mama();
Console.ReadKey();
}
static void mama()
{
FileStream fs2 = new FileStream("hello.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
fs2.Read(new byte[3], 0, 3);
}
can any one tell me why this error ?
error = The process cannot access the file 'C:\Users\iP\documents\visual studio 2015\Projects\ConsoleApplication32\ConsoleApplication32\bin\Debug\hello.txt' because it is being used by another process.
You're getting that error because you're passing FileShare.None to the second call. If you change that to FileShare.ReadWrite to match the first call, you won't have that problem.
The reason for this is because the FileStream constructor calls CreateFileW underneath, and if you take a look at the documentation for that function, it states:
You cannot request a sharing mode that conflicts with the access mode
that is specified in an existing request that has an open handle.
CreateFile would fail and the GetLastError function would return
ERROR_SHARING_VIOLATION.
You already have an open handle from the first request using FileAccess.ReadWrite as the access mode, which conflicts with FileShare.None in the second call.
Because your code never closes the file and has an open handle to it
If you can, always use the using statement, it will flush and close the file
using(var fs = new FileStream(...))
{
// do stuff here
} // this is where the file gets flushed and closed
If 2 methods are working on the same file, pass the FileStream in
static void mama(FileStream fs )
{
fs .Read(new byte[3], 0, 3);
}

C# Write / Read file, should I use a lock

I need advice whether or not using a lock (ReaderWriterLockSlim).
A user interacts on screen, and data can be saved into a file :
XmlSerializer xmlserializer = new XmlSerializer(typeof(MyFile));
FileStream fs = new FileStream(fileName, FileMode.Create,FileAccess.ReadWrite);
xmlserializer.Serialize(fs, this);
fs.Close();
In parallel, I have a timer (thus same thread, System.Windows.Forms.Timer), which checks this same file size and sends it to a server if modified.
I'll use File.ReadAllBytes as this is a rather small file.
Should I use a lock since writing filestream takes some time ?
I wonder if the timer can cause problem (I don't have a clear understanding if it preempts).
Thanks for any advice.
In WinForms an event never interrupts a running method running in the same thread (i.e. in the UI thread). Any timer_Tick (from System.Windows.Forms.Timer) will be delayed until the serializing code is finished.
(I assume that you are not using async calls.)
You can read the file size directly from the FileStream before closing it.
var xmlserializer = new XmlSerializer(typeof(MyFile));
using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite)) {
xmlserializer.Serialize(fs, this);
Console.WriteLine(fs.Length); // <=========
} // The using-statement automatically closes fs
If you need to know whether the file changed in another routine, why don't you just use a flag?
public static bool FileHasChanged { get; set; }
...
var xmlserializer = new XmlSerializer(typeof(MyFile));
using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite)) {
xmlserializer.Serialize(fs, this);
}
FileHasChanged = true;
In the other routine (timer_Tick I think):
if (MyFile.FileHasChanged) {
//TODO: Send file to server.
MyFile.FileHasChanged = false;
}
Since everything is running in the same thread, no locking is required.
Another question is whether you really need a file or whether you could just write to a MemoryStream and then use this memory stream to send the data to the server. If you still need the file, you could write to it using the same memory stream and serialize only once. The memory stream would replace the Boolean flag for the communication between the two routines. After sent to the server, the memory stream would be set to null after calling Dispose() (instead of MyFile.FileHasChanged = false;).
That would be more in the sense of Eric Lippert's comments.

Modify File Stream in memory

I am reading a file using StreamReader fileReader = File.OpenText(filePath). I would like to modify one line in the file in memory and push the modified stream to another method.
What I would like to avoid is reading the whole file into a string and modifying the string (doesn't scale). I would also like to avoid modifying the actual file.
Is there a straightforward way of doing this?
There is no built-in way to do that in .Net framework.
Stream and StreamReader/StreamWriter classes are designed to be chained if necessary (like GZipStream wraps stream to compress it). So you can create wrapper StreamReader and update data as you need for every operation after calling wrapped reader.
You can open two stream -one for read, one for write- at the same time. I tested simple code that works, but not sure that's what you want:
// "2.bar\r\n" will be replaced by "!!!!!\r\n"
File.WriteAllText("test.txt",
#"1.foo
2.bar
3.fake");
// open inputStream for StreamReader, and open outputStream for StreamWriter
using (var inputStream = File.Open("test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var reader = new StreamReader(inputStream))
using (var outputStream = File.Open("test.txt", FileMode.Open, FileAccess.Write, FileShare.Read))
using (var writer = new StreamWriter(outputStream))
{
var position = 0L; // track the reading position
var newLineLength = Environment.NewLine.Length;
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
// your particular conditions here.
if (line.StartsWith("2."))
{
// seek line start position
outputStream.Seek(position, SeekOrigin.Begin);
// replace by something,
// but the length should be equal to original in this case.
writer.WriteLine(new String('!', line.Length));
}
position += line.Length + newLineLength;
}
}
/* as a result, test.txt will be:
1.foo
!!!!!
3.fake
*/
As you can see, both streams can be accessed by StreamReader and StreamWriter at the same time. And you can also manipulate both read/write position as well.

Unable to access a file on second call to same function in c#

I am writing to a file through a function. On the first call I am able to write to the file but on the second call I get an exception:
The process cannot access a file because it is being used by some other process.
Basically the function I am calling starts a System.Diagnostics.Process process whose output I have to write to a file with the same name and location each time the function gets called. But whenever the function gets called for the second time I get the exception.
I have tried
Byte[] info = new UTF8Encoding(true).GetBytes(contents);
if (!File.Exists(fileName))
{
// Create the file.
using (FileStream fs = File.Create(fileName))
{
fs.Write(info, 0, info.Length);
fs.Close();
}
}
using (FileStream file_write = File.Open(fileName,FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
file_write.Write(info,0,info.Length);
file_write.Close();
}
and
File.writealltext(filename,contents)
and
using (StreamWriter file_write = new StreamWriter(File_path))
{
file_write.WriteLine(File_data);
file_write.Close();
}
Nothing worked.
Can anyone suggest any other way of doing this I am really stuck.
You need to use lock so that way the processes will wait for each other to finish writing.
static object obj = new object();
static void WriteOnFile(byte[] data)
{
lock(obj)
{
FileStream file_write = new FileStream(ileName,FileMode.Open, FileAccess.ReadWrite);
file_write.Write(data,0,data.Length);
file_write.Close();
}
}

copying file, file not disposed

I have the following code for copying file:
var copedFile = ConfigurationManager.AppSettings["PathToFirebirdDB"] + ".001";
using (var inputFile = new FileStream( ConfigurationManager.AppSettings["PathToFirebirdDB"],
FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var outputFile = new FileStream(copedFile, FileMode.Create))
{
var buffer = new byte[0x10000];
int bytes;
while ((bytes = inputFile.Read(buffer, 0, buffer.Length)) > 0)
{
outputFile.Write(buffer, 0, bytes);
}
}
}
This code works fine only one time. The next time I get the folowing message:
The process cannot access the file 'D:\Programs\IBExpert\db.fdb.001' because it is being used by another process. System.IO.IOException: The process cannot access the file 'D:\Programs\IBExpert\db.fdb.001' because it is being used by another process.
Why? There are using block.
If you try to reopen the file just after closing it, there is a chance the file is still considered open by the system because it actually is.
A typical reason is that a virus scanner is keeping the file open to ensure it is not infected, this happens in the background and might continue running after you have closed the file yourself.
Probably because you are not closing the files.
BTW why don't you just use File.Copy?

Categories

Resources