Reputation: 115
I have a watcher method i'm calling from the constructor of fomr1:
FileSystemWatcher watcher;
private void WatchDirectory()
{
watcher = new FileSystemWatcher();
watcher.Path = userVideosDirectory;
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size;
watcher.Filter = "*.mp4";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
Then the Onchanged event:
private void OnChanged(object source, FileSystemEventArgs e)
{
var info = new FileInfo(e.FullPath);
fileforupload = info.FullName;
if (IsFileLocked(info) == false)
{
sy.SetResult(true);
watcher.EnableRaisingEvents = false;
watcher.Dispose();
}
}
And this is the IsFileLocked method:
protected virtual bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
return true;
}
finally
{
if (stream != null)
stream.Close();
}
And i'm using it in this method:
public string SendResponse(HttpListenerRequest request)
{
sy = new TaskCompletionSource<bool>();
WatchDirectory();
sy.Task.Wait();
Youtube_Uploader youtubeupload = new Youtube_Uploader(fileforupload);
return false;
}
The exception is in the OnChanged event on the line:
sy.SetResult(true);
sy is:
TaskCompletionSource<bool> sy;
In the OnChanged method i did:
watcher.EnableRaisingEvents = false;
watcher.Dispose();
But still getting sometimes the exception. The exception is:
An attempt was made to transition a task to a final state when it had already completed
System.InvalidOperationException was unhandled
_HResult=-2146233079
_message=An attempt was made to transition a task to a final state when it had already completed.
HResult=-2146233079
IsTransient=false
Message=An attempt was made to transition a task to a final state when it had already completed.
Source=mscorlib
StackTrace:
at System.Threading.Tasks.TaskCompletionSource`1.SetResult(TResult result)
at Automatic_Record.Form1.OnChanged(Object source, FileSystemEventArgs e) in d:\C-Sharp\Automatic_Record\Automatic_Record\Automatic_Record\Form1.cs:line 197
at System.IO.FileSystemWatcher.OnChanged(FileSystemEventArgs e)
at System.IO.FileSystemWatcher.NotifyFileSystemEventArgs(Int32 action, String name)
at System.IO.FileSystemWatcher.CompletionStatusChanged(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* overlappedPointer)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
InnerException:
Upvotes: 1
Views: 2336
Reputation: 1100
This is happening because FileSystemWatcher fire multiple onChanged event for any single change. So before you disable EnableRaisingEvent watcher could have fired multiple onChanged event. You need to put locking in your onChanged method or instead of using TaskCompletionSource.SetResult use TaskCompletionSource.TrySetResult.
See this for details on TrySetResult: https://msdn.microsoft.com/en-us/library/dd449176(v=vs.110).aspx
Upvotes: 3