Search code examples
c#multithreadingwinformswinapipinvoke

The main form is frozen after finishing copying file (with a progress indicator) using CopyFileEx?


I have a main form, this form has a button clicking on which will show the copying window with a progressbar. I use a thread to do the copying job, however after finishing the copying (the file is copied OK and the copying window is closed) the main form is frozen (the controls on form seem not to be interactive with). The Task Manager shows that there is not much work (0%). There is something strange here. Here is the code for the copying dialogue, please see:

public partial class FileCopier : Form
{
    [DllImport("Kernel32")]
    private extern static int CopyFileEx(string source, string destination, CopyProgressRoutine copyProgress, int data, ref int cancel, int flags);
    private delegate int CopyProgressRoutine(long totalBytes, long bytesCopied, long streamSize, long streamCopied, int streamNumber, int callBackReason, int source, int destination, int data);
    public FileCopier()
    {
        InitializeComponent();            
    }
    #region private members
    int cancel;
    int copyFinished = -1;                
    #endregion
    #region public methods
    public void Copy(string source, string destination)
    {            
        CoreHandling(source, destination);            
    }
    public void MoveFile(string source, string destination)
    {
        CoreHandling(source, destination);
        if (cancel == 0)//If there is no canceling action
        {
            //Delete the source file
            File.Delete(source);
        }            
    }
    #endregion
    #region private methods
    private void CoreHandling(string source, string destination)
    {
        startTime = DateTime.Now;
        ThreadStart ths = delegate
        {
            CopyFileEx(source, destination, UpdateCopyProgress, 0, ref cancel, 1);
        };
        new Thread(ths).Start();
        ShowDialog();
        while (copyFinished == -1)
        {
            Thread.Sleep(10);
        }
        copyFinished = -1;
    }
    private int UpdateCopyProgress(long totalBytes, long bytesCopied, long streamSize, long streamCopied, int streamNumber, int callBackReason, int source, int destination, int data)
    {
        if (InvokeRequired)
        {                
            Invoke(new CopyProgressRoutine(UpdateCopyProgress), totalBytes, bytesCopied, streamSize, streamCopied, streamNumber, callBackReason, source, destination, data);
        }
        else
        {
            int percentage = (int)(((double)bytesCopied / totalBytes) * 100);
            progressBar.Position = percentage;
            Application.DoEvents();
            if (totalBytes == bytesCopied || cancel == 1)
            {
                DialogResult = DialogResult.OK;                    
            }
        }            
        return 0;
    }
    #endregion
    private void buttonCancel_Click(object sender, EventArgs e)
    {
        cancel = 1;
    }
}

In the code for my main form, here is the Button Click event handler:

private void buttonCopy_Click(object sender, EventArgs e){
    using(FileCopier fileCopier = new FileCopier()){
         fileCopier.Copy("My source file", "My destination file");
    }
}

That's all, after finishing the copying, the method Copy() above should exit normally. I don't understand what's still doing after finishing the copying and makes my main form frozen.

Your help would be highly appreciated!


Solution

  • copyFinished is not modified anywhere and the main thread sleeps indefinitely