Napisałem kiedyś na swoje potrzeby klasę która kopiuje plik w nowym wątku. Może Ci się przyda :)
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Runtime.Remoting.Messaging;
namespace CopyService
{
class Copy
{
int BufferSize = 131072;
byte[] buffer;
FileStream reader;
FileStream writer;
long bytesTotal, bytesCopied;
int readData, progressPercentage;
private MyAsyncContext myTaskContext;
public void CopyFileAsync(string Source, string Destination)
{
CopyFileDelegate worker = new CopyFileDelegate(CopyFile);
AsyncCallback completedCallback = new AsyncCallback(CopyFileCompletedCallback);
lock (_sync)
{
if (_myTaskIsRunning)
throw new InvalidOperationException("The control is currently busy.");
AsyncOperation async = AsyncOperationManager.CreateOperation(null);
MyAsyncContext context = new MyAsyncContext();
bool cancelled;
worker.BeginInvoke(Source, Destination, async, context, out cancelled, completedCallback, async);
_myTaskIsRunning = true;
myTaskContext = context;
}
}
public event AsyncCompletedEventHandler CopyCompleted;
public event CopyProgressChangedEventHandler CopyProgressChanged;
protected virtual void OnCopyProgressChanged(object sender, CopyProgressChangedEventArgs e)
{
if (CopyProgressChanged != null)
{
CopyProgressChanged(this, e);
}
}
protected virtual void OnCopyCompleted(AsyncCompletedEventArgs e)
{
if (CopyCompleted != null)
{
CopyCompleted(this, e);
}
}
private readonly object _sync = new object();
private bool _myTaskIsRunning = false;
private delegate void CopyFileDelegate(string Source, string Destination, AsyncOperation async, MyAsyncContext asyncContext, out bool cancelled);
private void CopyFile(string Source, string Destination, AsyncOperation async, MyAsyncContext asyncContext, out bool cancelled)
{
cancelled = false;
try
{
buffer = new byte[BufferSize];
reader = new FileStream(Source, FileMode.Open, FileAccess.Read);
writer = new FileStream(Destination, FileMode.Append, FileAccess.Write);
bytesTotal = reader.Length;
int i = -1;
while (reader.Position < bytesTotal)
{
readData = reader.Read(buffer, 0, buffer.Length);
writer.Write(buffer, 0, readData);
writer.Flush();
i++;
bytesCopied = (long)(i * BufferSize) + (long)readData;
progressPercentage = Convert.ToInt32((decimal)bytesCopied / (decimal)bytesTotal * 100);
CopyProgressChangedEventArgs eArgs = new CopyProgressChangedEventArgs(bytesCopied, bytesTotal, progressPercentage, null);
async.Post(delegate(object e) { OnCopyProgressChanged(this, (CopyProgressChangedEventArgs)e); }, eArgs);
if (asyncContext.IsCancelling)
{
cancelled = true;
return;
}
}
}
catch (Exception exc)
{
AsyncCompletedEventArgs completedArgs = new AsyncCompletedEventArgs(exc, false, null);
async.PostOperationCompleted(delegate(object e) { OnCopyCompleted((AsyncCompletedEventArgs)e); }, completedArgs);
}
finally
{
reader.Close();
writer.Close();
}
}
private void CopyFileCompletedCallback(IAsyncResult ar)
{
CopyFileDelegate worker = (CopyFileDelegate)((AsyncResult)ar).AsyncDelegate;
AsyncOperation async = (AsyncOperation)ar.AsyncState;
bool cancelled;
worker.EndInvoke(out cancelled, ar);
lock (_sync)
{
_myTaskIsRunning = false;
myTaskContext = null;
}
AsyncCompletedEventArgs completedArgs = new AsyncCompletedEventArgs(null, cancelled, null);
async.PostOperationCompleted(delegate(object e) { OnCopyCompleted((AsyncCompletedEventArgs)e); }, completedArgs);
}
public bool IsBusy
{
get { return _myTaskIsRunning; }
}
public void CancelAsync()
{
lock (_sync)
{
if (myTaskContext != null)
myTaskContext.Cancel();
}
}
}
public delegate void CopyProgressChangedEventHandler(object sender, CopyProgressChangedEventArgs e);
public class CopyProgressChangedEventArgs : EventArgs
{
private long bytesCopied;
private long totalBytesToCopy;
private int progressPercentage;
private object userState;
public long BytesCopied
{
get { return bytesCopied; }
}
public long TotalBytesToCopy
{
get { return totalBytesToCopy; }
}
public int ProgressPercentage
{
get { return progressPercentage; }
}
public object UserState
{
get { return userState; }
}
public CopyProgressChangedEventArgs(long bytesCopied, long totalBytesToCopy, int progressPercentage, object userState)
{
this.bytesCopied = bytesCopied;
this.totalBytesToCopy = totalBytesToCopy;
this.progressPercentage = progressPercentage;
this.userState = UserState;
}
}
internal class MyAsyncContext
{
private readonly object _sync = new object();
private bool _isCancelling = false;
public bool IsCancelling
{
get
{
lock (_sync) { return _isCancelling; }
}
}
public void Cancel()
{
lock (_sync) { _isCancelling = true; }
}
}
}