As it was common to guess what kind of reason for this exception. But let me explain the exact scenario which am facing . Please find the overview of my code block.
Task.Factory.StartNew(()=> Method1());
private void Method1()
{
//A process which loads the file and uploads it to server. If the file was large, it will take some amount of time.
using (var fileStream = System.IO.File.OpenRead(filePath))
{
//Upload file
}
//Once uploads deletes from local.
File.Delete(path);
}
Before uploading the file delete method was called as I have used separate tasks . So I get the exception that process cannot access the file.
I should delete the file once upload was over. Need some suggestions on that.
TPL Continuewith
you can also make use of contnuewith over here because
you want to updload file
once update done you want to delete file
than you can do this
Task t =Task.Factory.StartNew(()=> Method1());//remove delete file form method one
t.ContinueWith((as)=> {File.Delete(path);} );
there might be syntax error in above code so please solve it in visual studio
Singling Construct
As you are updloading and delete file on different threds that I suggest you
make use of signaling construct
public class test
{
private static AutoResetEvent event_2 = new AutoResetEvent(false);
public void uploadfile()
{
///do file updating
//than give signale
event_2.set();
}
public void deletefile()
{
event_2.WaitOne();
//delete file
}
}
it doesn't seem thread issue , it look like file you want to delete is not present so its better you check file exists or not by file exits method
if (File.Exists(path))
{
File.Delete(path);
}
Related
I have problem with handling files passed to my application in OnFileActivated(). First, I've registred specific file extention in Package.appminifest of my application, so after tap into specific file my application starts and run OnFileActivated function.
In my case file is archive zipped with System.IO.Compression.ZipArchive, but I think it's not crutial here. Beggining of my function looks as follow:
protected override async void OnFileActivated(FileActivatedEventArgs args) {
base.OnFileActivated(args);
var file = args.Files[0];
using (var archive = ZipFile.OpenRead(file.Path)) {
...
As some of you can expect I get an error when I'm trying to access file in last line. I also tried different solutions as copying file into local folder and then access it, but also without luck.
Question
Is there any way to do such thing? Or maybe I'm doing it completely wrong way?
Using the Path property will not be useful for a brokered file (such as you get from Activation). Use the constructor that takes a Stream instead.
Here is the correct answer:
protected override async void OnFileActivated(FileActivatedEventArgs args) {
base.OnFileActivated(args);
var file = (StorageFile)args.Files[0];
using (var archive = new ZipArchive(await file.OpenStreamForReadAsync())) {
...
I haven't noticed before that ZipArchive have constructor which takes stream as a parameter.
I have an app that I want to download & upload a simple .txt file with a URL inside. I have downloaded Live Connect SDK V5.4, referenced the documentation, but it appears that the documentation is incorrect. The sample code uses event handlers for when a download/upload is complete, but that no longer can be used in V5.4.
I have two methods, downURL & upURL. I have started working on downURL:
private async void downURL()
{
try
{
LiveDownloadOperationResult download = await client.DownloadAsync("URL.txt");
}
catch { }
}
I am not sure what I am suppose to use for the path, I put "URL.txt" for now, I've seen some examples with "/me/". Do I need this? The file does not need to be visible to the user, as the user can't really do anything with it, but it is vital for the app to work.
My question is how do I use the LiveDownloadOperationResult download to save the file to Isolated Storage Settings, get the text contents, and put that in a string? Also, if you know how to upload the file back up, the upload event handler looks the same (but without the Result variable).
This code help you download content a file which you want. It get content have format OpenXML
Here, "item.id" is Id of "URL.txt".
private async void downURL()
{
try
{
LiveDownloadOperationResult operationResult = await client.DownloadAsync(item.id + "/Content?type=notebook");
StreamReader reader = new StreamReader(operationResult.Stream);
string Content = await reader.ReadToEndAsync();
}
catch { }
}
I am new to c# so please forgive my ignorance, I am running a fileSystemWatcher on a text file. And it is working fine, I can do some simple tasks after the file has changed. All but what I want to do.
I am trying to read the last line of the text file that has changed with this code
public void File_Changed( object source, FileSystemEventArgs e )
{
string MACH1 = File.ReadText(#"C:\MACHINE_1.txt").Last();
if (MACH1=="SETUP")
{
MACHINE1IND.BackColor = Color.Green;
}
else
{
MACHINE1IND.BackColor = Color.Red;
}
}
It works fine inside a button but not after file watcher.
Says it cannot find file?
One thing to be aware of is that the FSW can issue multiple change notifications during a save operation. You have no way of knowing when the save is complete. As a result, you need to always wrap your code in a try..catch block and support retry after a timeout to allow the file write to be completed. Typically, I will try to move the file to a temp location where I will do my processing. If the move fails, wait a couple seconds and try again.
As Jim Wooley explains in his answer, the file operation might still be in progress, when FSW fires a Created or Changed event. If FSW is used to communicate between two applications and you are in control of the "sending" application as well, you can solve the problem as follows:
Write the information to a temporary file. Close the file. Rename the temporary file and give it a definitive name.
In the other application (the receiver) watch for the Renamed event using the FileSystemWatcher. The renamed file is guaranteed be complete.
You'll have to check if the file exists before accessing it.
public void File_Changed(object source, FileSystemEventArgs e)
{
string filePath = #"C:\MACHINE_1.txt";
if(!File.Exists(filePath)) //Checks if file exists
return;
string MACH1 = File.ReadText(filePath).Last();
if (MACH1=="SETUP")
{
MACHINE1IND.BackColor = Color.Green;
}
else
{
MACHINE1IND.BackColor = Color.Red;
}
}
I would like to open a file, and if it does not exist create it, similar to this question
The catch is that if the file was newly created I perform some additional initialization logic.
I can use
await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists)
to open the file if it already exists, but how can I tell if the result of this operation was a newly created file or just opening an existing file? Is there a best practice here or am I stuck looking at the file create date or file size?
Ideally the code would look something like this:
var file = await folder.CreateFileAsync(fileName, CreationCollsionOption.OpenIfExists);
//How can I reliably tell if the file was new?
if (fileIsNew)
await InitializeFile(file);
With using the CreationCollsionOption.OpenIfExists there is no way to tell what's happened other than looking the CreatedDate or the Size of the file.
So I think you are better if you use the GetFileAsync (like in the linked question) and do your initilaize logic in the catch FileNotFoundException branch, because there is no File.Exists in WinRt
However there is a third solution where you enumerate the files in the directory and check for existence by hand:
var files = await folder.GetFilesAsync(CommonFileQuery.OrderByName);
var file = files.FirstOrDefault(x => x.Name == fileName);
if (file == null)
{
file = await GetFilesAsync(fileName);
await InitializeFile(file);
}
Note: in this case potentially you have to prepare to handle race conditions becase it can happen while you are processing the file list somebody creates the file before you (that's why there is no File.Exists method exists)
I had a similar situation where I wanted to determine if an app was running for the first time. Here's how I approached it.
try
{
await ApplicationData.Current.LocalFolder.GetFileAsync(FirstRunFile);
}
catch (FileNotFoundException)
{
isFirstRun = true;
}
if (isFirstRun) {
// Perform necessary initialization here
await ApplicationData.Current.LocalFolder.CreateFileAsync(FirstRunFile);
}
I have a program that roughly does this:
open a file to read from it.
close the file
Start a filewatcher to watch for changes in the file.
As soon as a change is detected, the filewatcher's EnableRaisingEvents flag is set to false and the process repeats from Step 1.
The problem is, after going from step 4 to step 1, it cannot read the file saying that it is being used by another Process.
Error I receive:
Unhandled Exception: System.IO.IOException: The process cannot access the file 'c:\test.xml' because it is being used by another process.
Whats going wrong? does the reader from Step 1 of my program still have the file open, or is some entirely different process accessing the file, or is it that filewatcher is still watching the file after moving to Step 1 from 4, despite setting the flag to false?
If your code is similar to this:
[STAThread]
static void Main(string[] args)
{
string file = "temp.txt";
ReadFile(file);
FileSystemWatcher fswatcher = new FileSystemWatcher(".\\");
fswatcher.Changed += delegate(object sender, FileSystemEventArgs e)
{
ReadFile(e.FullPath);
};
while (true)
{
fswatcher.WaitForChanged(WatcherChangeTypes.Changed);
}
}
private static void ReadFile(string file)
{
Stream stream = File.OpenRead(file);
StreamReader streamReader = new StreamReader(stream);
string str = streamReader.ReadToEnd();
MessageBox.Show(str);
streamReader.Close();
stream.Close();
}
If you are editing the file via notepad, then, when you click the save button, it keeps the file open, while as if when you just close the program and click save it doesn't. I do no know if this is a bug or an undocumented feature of notepad, but this just might be your problem. One way to fix this is to do the following:
In your anonymous delegate, or wherever you execute the call to ReadFile() call Thread.Sleep(1000), to have the program wait before reading the file and your code should work fine.
You can use a tool like Process Explorer from http://www.sysinternals.com to see who has the open handle to the process
The file is most likely held open by whatever caused the change notification to fire in the first place.
Beside other answers it is possible that when FileWatcher reacts file it not yet closed by that app. In step 1 try not to fail immediately but try several attempts with small delay.
Note: even if "file.txt" is open in Notepad, this code still works, because it is opening for read.
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
ReadFromFile(#"C:\file.txt");
Console.ReadLine();
}
static void ReadFromFile(string filename)
{
string line;
using (StreamReader sr = File.OpenText(filename))
{
line = sr.ReadLine();
while (line != null)
{
Console.WriteLine(str);
line = sr.ReadLine();
}
sr.Close();
}
}
}
Or just:
string text = System.IO.File.ReadAllText(#"C:\file.txt");
The problem is that the FileSystemWatcher tells you immediately when the file was created. It doesn't wait for the file to be released.
For instance, when you copy a large file which takes 3 seconds to copy, so you have to open the file after that.
http://www.codeproject.com/Questions/461666/FileSystemWatcher-issue-in-windows-application
Wait until file is unlocked in .NET
There are a number of things that could be going on.
First, make sure you properly dispose of the file writer (close isn't good enough) by utilizing the using clause around everything that implements IDisposable.
Second, it you are simply reading, make sure you have the correct flags set when opening the file.
To go any further it would help if you provided a code block which showed how you were accomplishing this; particularly around the reading of the file
You can use this MS utility openfiles to obtain list of opened files and understand who has opened the file.
openfiles /query
Also it allow to disconnect files opened by network users.
openfiles /disconnect /id XXXX
If you want use it for local PC you should set Maintain Objects List global flag:
openfiles /local on
Follow the link to get more details.