none
Release a file lock by a process without killing the process, Abort thread may be an option, I tried doing it but it did not work. RRS feed

  • Question

  • Hello, 

    I wanted to release a file lock by a process and delete the file. I don't want to kill the process instead I want to abort the thread. I did try aborting the thread but the thing is by getting the current thread and aborting it, it keeps on directing me to all the catch blocks that I have in my program and does not allow me to delete the file( the file is still not released). Is there a way without killing the process. Any other approach would be helpful. Thank you

    Thursday, October 24, 2019 1:48 PM

All replies


  • <button aria-label="down vote" aria-pressed="false" class="js-vote-down-btn grid--cell s-btn s-btn__unset c-pointer" data-selected-classes="fc-theme-primary" style="margin:2px;box-sizing:inherit;font:inherit;padding:0px;border-width:initial;border-style:none;border-color:initial;border-radius:3px;background-image:none;background-background-size:initial;background-repeat:initial;background-attachment:initial;background-origin:initial;background-clip:initial;outline:none;box-shadow:none;" title="This question does not show any research effort; it is unclear or not useful"><svg aria-hidden="true" class="svg-icon m0 iconArrowDownLg" height="36" viewBox="0 0 36 36" width="36"><path d="M2 10h32L18 26 2 10z"></path></svg></button><button aria-label="favorite" aria-pressed="false" class="js-favorite-btn s-btn s-btn__unset c-pointer py8" data-selected-classes="fc-yellow-600" style="margin:0px;box-sizing:inherit;font:inherit;padding:0px;border-width:initial;border-style:none;border-color:initial;border-radius:3px;background-image:none;background-background-size:initial;background-repeat:initial;background-attachment:initial;background-origin:initial;background-clip:initial;outline:none;box-shadow:none;" title="Click to mark as favorite question (click again to undo)"><svg aria-hidden="true" class="svg-icon iconStar" height="18" viewBox="0 0 18 18" width="18"><path d="M9 12.65l-5.29 3.63 1.82-6.15L.44 6.22l6.42-.17L9 0l2.14 6.05 6.42.17-5.1 3.9 1.83 6.16L9 12.65z"></path></svg>
    </button>

    How do I allow the current thread to safely exit and perform a delete action to some resources of the thread. I used Thread.Abort() but using that it seems that it does not release the resources. I am finding a way to allow the thread to safely exit and as soon as it exits, i want to perform the delete action. If any one has any examples or suggestions please contribute

    Thursday, October 24, 2019 2:55 PM
  • You send an Interrupt to the thread. This causes it to jump into the catch block for the TreadInterruptedException. In the catch block, you Close() and Dispose() the variable that you used for opening the file. This will release the lock.

    Thursday, October 24, 2019 3:45 PM
    Moderator
  • Thread.Abort should not be used, and isn't even supported on .NET core (see Thread.Abort)
    do you want to abort a thread in a different process? Or your own process?
    normally you stop the thread by setting a control value.
    Better yet: use Tasks instead of creating your own threads,
    then use CancellationTokenSource.
    Of course you still need to dispose the file stream correctly to release the file (using).


    Thursday, October 24, 2019 3:47 PM
  • The file is not used by a variable instead it is used by a command. The process that uses the file is DLL command . dssPut_Command("Compile " + SystemID + "abc.dss");
    Thursday, October 24, 2019 4:24 PM
  • so lets say, I am using a command that uses the file, I am not very sure how to use the Task process, this is what I have so far :

    var task = Task.Run(() =>
    {
    dssPut_Command("Compile " + SystemID + "abc.dss");
    ct.ThrowIfCancellationRequested();

    bool moreToDo = true;

    while (moreToDo)

    {

    if (ct.IsCancellationRequested)

    {
    // Clean up here, then...
    ct.ThrowIfCancellationRequested();
    }

    }
    },tokenSource2.Token);
    tokenSource2.Cancel();

    But even canceling the task wont release the file. I am not sure if I am doing it in the right way though. 


    • Edited by SarbeshB Thursday, October 24, 2019 4:28 PM
    Thursday, October 24, 2019 4:26 PM
  • in your code I don't see any file access.
    when the dssPut_Command is using a file it needs to dispose after use.

    How is the file closed then you don't abort the thread?

    Thursday, October 24, 2019 4:50 PM
  • Let me explain you what is going on, so dssPut_Command is taking abc.dss file, so lets say if there is an error in the file , if there is no error then it moves forward to the next process but if there is an error with the file lets say some input in the file are corrupted then I want to delete the file but in this case what is going on is, it keeps on locking the file, and says the file is being used by another process. I want to have a certain time out for the given action if it cannot be completed in certain time, I want to come out of that particular command and delete the file which in this case is abc.dss file but it is not allowing me to del the file. 
    Thursday, October 24, 2019 5:01 PM
  • Calling Abort on a thread immediately terminates it. If it has any cleanup code then that code won't run. To properly terminate a thread the thread needs to be aware of the termination and it has to decide when to honor it. You cannot "cleanly" terminate an arbitrary thread. Most of the time we use a ManualResetEvent to notify the thread when to terminate. When it is time to terminate you set the event. The thread itself checks the state of the event when it is ready to cleanly terminate. If the event is set then it returns which terminates the thread otherwise it continues doing whatever it was doing. This often happens at the start or end of a loop that is running indefinitely otherwise.

    //Not tested...
    private ManualResetEvent _terminate = new ManualResetEvent(false);
    
    //Thread function
    void DoingThreadWork ()
    {
       //Should we terminate yet?
       while (!_terminate.WaitOne())
       {
          //Do work that cannot be interrupted
       };
    }
    
    //Tell the thread to terminate
    _terminate.Set();
    
    //Wait for thread to terminate
    myThread.Join();
    If the thread only needs to run periodically then putting a timeout in the wait allows it to efficiently sleep until either it is time to run again or the terminate event gets set.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, October 24, 2019 5:23 PM
    Moderator
  • when an error while reading the file is not releasing the file, then you are probably missing a using statement.
     using (var sr = new StreamReader("TestFile.txt"))
     {
          while (sr.Peek() > -1)
          {
              DoSomething(sr); //even when this throws, file will be closed
          }
     }



    Thursday, October 24, 2019 5:26 PM
  • Unless you have a handle to the file you cannot "release it" outside of terminating the owning process. Even if you have the handle, closing it will probably crash the thread/process that is using it. Note that file handles are per process so file handle 1 in some arbitrary process isn't the same file handle 1 in your process.

    Personally it sounds like you have a design problem and you're simply trying to work around the problem rather than solving the underlying issue. Fix the underlying issue, whatever that is, that is causing the file handle to be left locked rather than trying to "unlock it". You'll stand a better chance of success and it will be more maintainable.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, October 24, 2019 5:28 PM
    Moderator
  • @EckiS, that makes sense but in my case, dssPutCommand takes in the abc.dss file and generates a csv file and gives it to the output manager, I am dealing with a engine and I don't have to worry about how the dssPutCommand is implemented. When the file does not have any kind of error with it then it successfully generates the output of something, but when it encounters that the input file has some error, in that case it will lock the file. After ending all the execution and going inside the input manager directory that has all the input dss file, if I try to delete it, it does not allow me, that's the reason I was thinking of aborting the thread which also did not work in my case. Lets say:

    dssPut_Command("Compile " + SystemID + "abc.dss");
    dssPut_Command("Compile " + SystemID + "def.dss");

    If abc.dss has some kind of error in the file then it will stick to that part so to avoid that I used task.run so if the wait time is more than 2 second it moves towards the next command. 

    var task = Task.Run(() => dssPut_Command("Compile " + SystemID + "abc.dss");

    if (!task.Wait(TimeSpan.FromSeconds(2)))
    {

    //implement other command

    }

    it then executes the command  having the file  def.dss , similarly, I have more dssput command. So, in my case it is not locking def.dss and I am being able to delete def.dss but the abc.dss is being locked.

    Thursday, October 24, 2019 6:44 PM
  • @CoolDadTx please see my reply to @EckiS. This will give you the situation I am dealing with. I am not sure if the design has an issue. If you could provide an example of unlocking the handle I can try that too. I tried everything I found so far.
    • Edited by SarbeshB Thursday, October 24, 2019 6:50 PM
    Thursday, October 24, 2019 6:48 PM
  • aborting a thread will not help you when the file handle is not closed.
    you will need to look at the code opening "abc.dss".

    when waiting 2 seconds sometimes releases the file, I assume that the finalizer thread is cleaning up for you.
    But that is not deterministic.
    You need to use Dispose, anything else is going to cause trouble.

    Visual Studio 2019 will even warn you when you fail to dispose:
    "Warning CA2000 Call System.IDisposable.Dispose on object created by 'new StreamReader("")' before all references to it are out of scope."
    Thursday, October 24, 2019 7:04 PM
  • waiting for 2 seconds does not releases the file , all I am saying is if 

    dssPut_Command("Compile " + SystemID + "abc.dss");

    is used alone without putting task.run with it then while debugging it keeps on sticking to that line of code so to come out from that I used 

    var task = Task.Run(() => dssPut_Command("Compile " + SystemID + "abc.dss"), tokenSource2.Token);
    if (!task.Wait(TimeSpan.FromSeconds(2)))
    {

    dssPut_Command("Compile " + SystemID + "def.dss");

    ...... and many more dssPut_Command

    }

    After the program is completed the file having issue which is abc.dss is locked but def.dss is fine, so waiting 2 seconds doesnot releases the file. 

    Thursday, October 24, 2019 7:12 PM
  • So, how do I use Dispose in this case, I have tried using Thread.Dispose() and then tried to delete the file, it still did not work. 
    Thursday, October 24, 2019 7:13 PM
  • @CoolDadTx , I exactly wanted to do whatever you explained, terminate it cleanly but I am not able to do it. How do I use that part in my case. 

    var tokenSource2 = new CancellationTokenSource();
    CancellationToken ct = tokenSource2.Token;
    var task = Task.Run(() => dssPut_Command("Compile " + SystemID + "_LineDSS.dss"), tokenSource2.Token);


    if (!task.Wait(TimeSpan.FromSeconds(2)))
    {
    ct.ThrowIfCancellationRequested();

    bool moreToDo = true;
    while (moreToDo)
    {
    // Poll on this property if you have to do
    // other cleanup before throwing.
    if (ct.IsCancellationRequested)
    {
    // Clean up here, then...
    ct.ThrowIfCancellationRequested();
    }
    tokenSource2.Cancel();
    }

    }

    so if the task var task = Task.Run(() => dssPut_Command("Compile " + SystemID + "_LineDSS.dss"), tokenSource2.Token); does not complete in 2 seconds I want to terminate the thread cleanly

    Thursday, October 24, 2019 7:22 PM
  • Again, you cannot do this. The fact that you're trying is a clear indication that you have a design problem. 

    Is `dssPut_Command` a native function? If it is locking a file and you cannot change how it works then you have no choice but to consider alternatives. Here's a couple that come to mind:

    1) Move the call to that command to a standalone process that executes the command. Then if you wait long enough and it doesn't complete you can kill the process which releases the file.

    2) Copy the file to the temp directory with a temporary name (Path.GetTempFileName) and then have your command run against that. If it times out then let it go, assuming it isn't running in the background or, worst case, kill the thread. The original file is still available and can be used again if needed.

    Note that you are mentioning Task here but using thread. They ARE NOT the same thing and SHOULD NOT be combined together. If you're mixing the 2 then you have yet another design problem that you need to solve that is making this problem even worse. Fix that first.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, October 24, 2019 7:26 PM
    Moderator
  • depending on how you read the file, you need to dispose a StreamReader or a Stream, or...
    I already posted sample code.

    This is my last post in this thread as you obviously are ignoring most of what I write, anyway.
    Thursday, October 24, 2019 7:26 PM
  • Well thank you for letting me know about this. I really appreciate your time. If I could go and dispose a streamReader I would do that but my problem is I am using some dll library so there is no way I can make changes inside the dssput_command implementation. 
    Thursday, October 24, 2019 7:45 PM
  • Also just letting you know even while closing and trying to dispose the stream, it will throw and exception. 
    Monday, October 28, 2019 8:27 PM