Search code examples
c#timerthread-safetyobjectdisposedexception

How can I prevent my System.Timers.Timer from raising the Elapsed event after it got stopped?


I have the followig code:

using (FileStream sourceStream = sourceFile.Open())
{
    using (FileStream targetStream = File.Create(targetFilePath))
    {
        using (Timer timer = new Timer(250))
        {
            timer.Elapsed += (sender, e) =>
            {
                if (this.FileCopyProgressChanged != null)
                {
                    //Here the ObjectDisposedException appears
                    this.FileCopyProgressChanged(this,
                        new CopyProgressEventArgs(
                            sourceStream.Length,
                            targetStream.Length));
                }
            };

            timer.Start();

            sourceStream.CopyTo(targetStream);

            timer.Stop();
        }
    }
}

My timer elapses every 250 milliseconds and raises an event with information about the stream copy progress. The problem is, that sometimes in the timer event, a ObjectDisposedException gets thrown, because the streams are not opened anymore.

How can I prevent my timer from raising the elapsed event after my streams are disposed?


Solution

  • Why not just do this, no timers required:

    using (FileStream sourceStream = sourceFile.Open())
    {
        using (FileStream targetStream = File.Create(targetFilePath))
        {
            int bytesTotal = sourceStream.Length;
            int bytesCurrent = 0;
            var buffer = new byte[32*1024];
            int bytes;
            while ((bytes = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                targetStream.Write(buffer, 0, bytes);
                bytesCurrent += bytes;
                FileCopyProgressChanged(this,
                    new CopyProgressEventArgs(bytesTotal, bytesCurrent));
            }
        }
    }