Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Monday, October 19, 2015 5:04 AM
I'm using: System.Threading.Tasks.TaskCompletionSource
First i'm using a FileSystemWatcher:
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 in the OnChanged event i'm checking if the file i'm watching is still locked or not:
rivate 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();
}
}
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();
}
//file is not locked
return false;
}
The variable sy is: TaskCompletionSource sy; and it's global.
This is where i'm using the sy first time and in the OnChanged event is the second time the program using the sy:
TaskCompletionSource<bool> sy;
public string SendResponse(HttpListenerRequest request)
{
string result = "";
string key = request.QueryString.GetKey(0);
if (key == "cmd")
{
if (request.QueryString[0] == "uploadstatus")
{
switch (Youtube_Uploader.uploadstatus)
{
case "uploading file":
return "uploading " + Youtube_Uploader.fileuploadpercentages;
case "status":
return Youtube_Uploader.fileuploadpercentages.ToString();
case "file uploaded successfully":
Youtube_Uploader.uploadstatus = "";
return "upload completed," + Youtube_Uploader.fileuploadpercentages + ","
+ Youtube_Uploader.time;
default:
return "upload unknown state";
}
}
if (request.QueryString[0] == "nothing")
{
return "Connection Success";
}
if (request.QueryString[0] == "start")
{
StartRecrod();
result = "Recording started";
}
if (request.QueryString[0] == "stop")
{
dirchanged = false;
StartRecrod();
result = "Recording stopped and preparing the file to be shared on youtube";
sy = new TaskCompletionSource<bool>();
WatchDirectory();
sy.Task.Wait();
StreamWriter w = new StreamWriter(userVideosDirectory + "\\UploadedVideoFiles.txt",true);
w.WriteLine(fileforupload);
w.Close();
uploadedFilesList.Add(fileforupload);
Youtube_Uploader youtubeupload = new Youtube_Uploader(uploadedFilesList[0]);
}
}
else
{
result = "Nothing have been done";
}
return result;
}
The exception is on the line:
sy.SetResult(true);
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 305
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:
Line 305 is:
sy.SetResult(true);
My question is why i'm getting this exception maybe since i'm trying to make this iperation too quick few times in a row ? And how should i handle it if the file is locked is should not get there on the next time only if the file is not locked anymore.
I messed it up. The idea is to watch the latest created file and once it's finished creating and building and using the file so the file is unlocked then watch for the next last created file if there is any newer file then the last watched !!!
I tried to change the OnChanged event code to this:
if (IsFileLocked(info) == false)
{
watcher.EnableRaisingEvents = false;
sy.SetResult(true);
sy = new TaskCompletionSource<bool>();
watcher.EnableRaisingEvents = true;
}
But getting same exception.
I'm using a web server on my pc and client on my android smartphone using java.
When i touch the android device smartphone screen i see using a break point that it's getting and stop inside the SendResponse method it stop on the line:
dirchanged = false;
So i know the status now is sstop"
Then it's doing the method WatchDirectory then after sometimes it's getting to the sy.Task.Wait then it's doing the StreamWriter text file instance of the UploadedVideoFiles.txt
The problem as i see it with using the break point is that there is no a real order it's calling the WatchDirectory then after few second making the sw.Task.Wait then in the middle doing the StreamWriter instance.
The problem is when i touch the screen it's working on the file so i want i need to watch the file untill it's not locked(not in use) then i know the file is unlocked and do all the stuff in the OnChanged event.
All replies (1)
Monday, October 19, 2015 3:00 PM âś…Answered
The problem is that you're trying to use TaskCompletionSource which is designed for Task work on code that isn't using tasks. This isn't going to work. Unless you are using Task and/or await/async then you shouldn't be using TCS. It appears that all you're really trying to do is wait for some work to complete. In that case use one of the standard sync objects like ManualResetEvent. That is what they are designed for. You can reset your event before you start the worker thread (which is what FileSystemWatcher users), set the event when your FSW finishes and then Wait in the main thread.
You cannot and should not be using TCS in this code since you have no tasks.
Michael Taylor
http://blogs.msmvps.com/p3net