0

Here, i have a some format file which contains 2 folders and some xml files in that folders.While opening that file i extract that file in temporary location like appdata.

Then read each and every file and rendered some UI elements based upon the saved file texts.While opening i will show the waiting indicator box and that loaded process are doing in background with dispatcher.

If i want to abort that operation click abort and not needed to perform any operations(Render UI elements).Here i will delete that temporary location it will show "the process cannot access this file because it is used by another process" exception.May i know how to delete that file or which process is used that file?

Here is my code:

I made an edit, Using CancellationToken for abort all methods.

var backGroundWorker = new CancelSupportedBackgroundWorker { WorkerSupportsCancellation = true };
CancellationTokenSource source = new CancellationTokenSource(); 
AlertBox = new AlertBox { IsBusy = true };
AlertBox.WaitingText = Loading;
AlertBox.WaitingHeaderText = Loading Indicator;
AlertBox.AbortButton.Click += (obj, arg) =>
{
    App.Current.Dispatcher.Invoke(new Action(() =>
    {
        string tempDir = C:\Users\Lenovo\AppData + FileAndDirectoryConstants.TempDirFolder;
        if (Directory.Exists(tempDir))
        {
            Directory.Delete(tempDir, true);
        }
      }));

GC.Collect();
source.Cancel();
GC.WaitForPendingFinalizers();
backGroundWorker.CancelAsync();
backGroundWorker.Abort();
backGroundWorker.Dispose();
}

backGroundWorker.DoWork += (obj, arg) =>
{
    try
    {
        RenderUiElements(fileName,(CancellationToken)arg.Argument);
    }
    catch (ThreadAbortException)
    {
        Dispatcher.Invoke(() =>
        {
            AlertBox.IsBusy = false;
        }, System.Windows.Threading.DispatcherPriority.Background);
        arg.Cancel = true;
    }
};
backGroundWorker.RunWorkerCompleted += (obj, arg) =>
{
    AlertBox.isBusy = false;
}
backGroundWorker.RunWorkerAsync(source.Token);

private void RenderUiElements(string fileName,CancellationToken token)
{
    try
    {
        if(token != default(CancellationToken))
           if(token.isCancellationRequested)
              return;
        App.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
        delegate ()
        {
            using (fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
            {                                
                LoadReport(fileStream, fileName,token);
            }
        }));
    }
    catch (ThreadAbortException)
    {
        return;
    }
    finally
    {
        if (fileStream != null)
        {
            fileStream.Close();
            fileStream.Dispose();
        }
    }
}
Pandi
  • 471
  • 3
  • 17
  • I think, `LoadReport` is still using `fileStream` when you abort the operation and that is the reason why you are getting the message – Ben Aug 08 '17 at 06:06
  • Yes, That is the reason. Because Loadreport doing some operations using that filestream.At that time we need to abort that operation and try to delete that folder. – Pandi Aug 08 '17 at 06:15
  • Here are a few approaches: [Is there a way to check if a file is in use?](https://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use/11060322#11060322) – Jeremy Thompson Aug 08 '17 at 06:22
  • That approach is used to check if the file is locked or not. But i need to delete that file. – Pandi Aug 08 '17 at 06:32
  • Why not just cancel the operations in `LoadReport`? After this, you should be able to delete the file – Ben Aug 08 '17 at 07:25
  • I also try cancel the operation of LoadReport using Cancellationtoken. It is not worked as expected – Pandi Aug 08 '17 at 08:42

2 Answers2

1

There are only 2 ways you can delete a file in use by another process

  • force all file handles currently open on a file to be closed, then delete the file
  • P/Invoke the Windows MoveFileEx function, and use the MOVEFILE_DELAY_UNTIL_REBOOT flag, with a NULL destination name. This will delete the file when you reboot.

I'd recommend you perform the latter, as doing the former is nasty and could cause serious problems for other running apps. For more info on the latter, see http://www.pinvoke.net/default.aspx/kernel32.movefileex

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • How to close **all file handles currently open on a file** – Pandi Aug 08 '17 at 06:07
  • 2
    I deliberately didn't give an example for that because it's a terrible thing to do. If you want to do it, you'll need to do a bit of googling. Be sure you actually want to do it and it's not your own code still having an open handle to a particular file. Do please consider taking the latter approach – Caius Jard Aug 08 '17 at 06:09
0

Finally, I found that solution,

Here the Filestream object is doesn't properly disposed which is disposed only after LoadReport method completely. If i click abort while doing LoadReport the filestream doesn't disposed.So that error occurred.

So clear the Filestream object in LoadReport() method.

private void LoadReport(stream filestream,CancellationToken token)
{
 filestream.Close();
 filestream.Dispose();
}
Pandi
  • 471
  • 3
  • 17