This sample does a file search asynchronously. At the end of the search the progress dialog pauses and closes itself. Internally a timer is used to initiate this automatic close of the progress dialog. AsynchFileFinder is the BackgroundWorker derived object.
Here is th Xaml for the dialog:
<Window x:Class="FindingFilesDlg"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Finding modified files" Height="167" Width="514" Closing="Window_Closing" Loaded="Window_Loaded">
<Grid>
<Button Height="23" HorizontalAlignment="Right" Margin="0,0,12,12" Name="butCancel" VerticalAlignment="Bottom" Width="91" Click="butCancelDone_Click">_Cancel</Button>
<TextBlock Height="21" Margin="12,15,0,0" Name="tbActivity" VerticalAlignment="Top" Text="Searching for modified files:" HorizontalAlignment="Left" Width="Auto" />
<ProgressBar Margin="12,61,0,52" Name="progressBar" HorizontalAlignment="Left" Width="427" />
<TextBlock Margin="0,61,16,52" Name="tbPercentage" Text="0%" HorizontalAlignment="Right" Width="31" TextAlignment="Right" />
</Grid>
</Window>
Here is the code for the dialog:
public partial class FindingFilesDlg : Window
{
AsyncFileFinder m_AsyncFileFinder = null;
DispatcherTimer m_Timer = new DispatcherTimer();
IEnumerable<FileSystemInfo> m_FilesFound =
new FileSystemInfo[0];
int countDown = 1;
const int SECOND = 10000000;
bool m_Completed = false;
public FindingFilesDlg(string rootDir, FileSearchRules fsr)
{
InitializeComponent();
tbActivity.Text = "Preparing to search \'" +
rootDir + "\' for modified files:";
InitialiseTimer();
InitialiseAsyncFileFinder(rootDir, fsr);
}
private void InitialiseAsyncFileFinder(
string rootDir,
FileSearchRules fsr)
{
// The BackgroundWorker derived object
m_AsyncFileFinder = new AsyncFileFinder(rootDir, fsr);
m_AsyncFileFinder.ProgressChanged +=
new ProgressChangedEventHandler(
AsynchFileFinder_ProgressChanged);
m_AsyncFileFinder.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(
AsynchFileFinder_RunWorkerCompleted);
}
private void InitialiseTimer()
{
// Disable timer
m_Timer.IsEnabled = false;
// Set timer event interval
m_Timer.Interval = new TimeSpan((long)(1 * SECOND));
// Timer events
m_Timer.Tick += new EventHandler(timer_Tick);
}
public IEnumerable<FileSystemInfo> FilesFound
{
get { return m_FilesFound; }
}
void AsynchFileFinder_RunWorkerCompleted(
object sender,
RunWorkerCompletedEventArgs e)
{
if (!e.Cancelled)
{
m_Completed = true;
m_FilesFound = m_AsyncFileFinder.Files;
tbActivity.Text = "Finished searching \'" +
m_AsyncFileFinder.SearchDirectory +
"\', " + m_FilesFound.Count().ToString() +
" files found";
progressBar.Value = progressBar.Maximum;
tbPercentage.Text = "100%";
UpdateDoneButton();
// wait several seconds before closing the dialog
m_Timer.Start();
}
}
void UpdateDoneButton()
{
string str = "_Done (" +
countDown.ToString() + ")";
butCancel.Content = str;
}
bool textUpdated = false;
void AsynchFileFinder_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
Debug.Assert((e.ProgressPercentage >= 0) &&
(e.ProgressPercentage <= 100));
progressBar.Value = e.ProgressPercentage;
tbPercentage.Text = e.ProgressPercentage.ToString() +
"%";
if ((e.ProgressPercentage > 1) && !textUpdated)
{
textUpdated = true;
tbActivity.Text = "Searching \'" +
m_AsyncFileFinder.SearchDirectory +
"\' for modified files (" +
m_AsyncFileFinder.NumFilesToSearch.ToString() +
" files to search) :";
}
}
private void Window_Closing(object sender, CancelEventArgs e)
{
CancelAsyncFileFinder();
if (m_Timer.IsEnabled)
StopTimer();
m_AsyncFileFinder.Dispose();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
m_AsyncFileFinder.RunWorkerAsync();
tbActivity.Text = "Searching \'" +
m_AsyncFileFinder.SearchDirectory +
"\' for modified files:";
}
// wait several seconds before closing the dialog
void timer_Tick(object sender, EventArgs e)
{
--countDown;
UpdateDoneButton();
if (countDown == 0)
{
StopTimer();
DialogResult = m_Completed;
}
}
private void StopTimer()
{
m_Timer.Stop();
}
private void butCancelDone_Click(object sender,
RoutedEventArgs e)
{
if (!m_Completed)
{
CancelAsyncFileFinder();
if (m_Timer.IsEnabled)
StopTimer();
}
DialogResult = m_Completed;
}
private void CancelAsyncFileFinder()
{
if (m_AsyncFileFinder.IsBusy)
m_AsyncFileFinder.CancelAsync();
}
}
Here is the code for the background worker object:
internal class AsyncFileFinder : BackgroundWorker
{
private FileSearchRules FileSearchRules { get; set; }
string m_RootDir = string.Empty;
List<System.IO.FileSystemInfo> files = new
List<System.IO.FileSystemInfo>();
int m_NumberFilesToSearch = 0;
// Pass required info in through constructor,
// cant change it whilst a search is underway
public AsyncFileFinder(string rootDir,
FileSearchRules fsr) : base()
{
this.WorkerReportsProgress = true;
this.WorkerSupportsCancellation = true;
m_RootDir = rootDir;
FileSearchRules = new FileSearchRules(fsr);
}
public string SearchDirectory
{
get { return m_RootDir; }
}
public IEnumerable<FileSystemInfo> Files
{
get
{
if (IsBusy) // No access while thread active
return new List<FileSystemInfo>();
else
return files.AsReadOnly();
}
}
// Total number of files that will be checked
public int NumFilesToSearch
{
get
{
return m_NumberFilesToSearch;
}
}
protected override void OnDoWork(DoWorkEventArgs e)
{
bool cancelled = false;
double progress = 0;
double prevProgress = 0;
files = new List<FileSystemInfo>();
DirectoryInfo targ = new DirectoryInfo(m_RootDir);
// Count the number of files to process first
foreach (System.IO.FileSystemInfo fsi in
targ.IterateFiles(true))
{
if (CancellationPending)
{
cancelled = true;
break;
}
Interlocked.Increment(ref
m_NumberFilesToSearch);
}
int count = 0;
if (!cancelled)
{
foreach (FileSystemInfo fsi in
targ.IterateFiles(true))
{
if (CancellationPending)
{
cancelled = true;
break;
}
++count;
// progress as a percentage
progress = (100.0 * (double)count /
(double)m_NumberFilesToSearch) + 0.5;
// Report every 1% of progress
if ((progress - prevProgress) > 1.0)
{
ReportProgress((int)(progress));
prevProgress = progress;
}
if (FileSearchRules.PassesRules(fsi))
{
files.Add(fsi);
}
}
}
e.Cancel = cancelled;
}
}
No comments:
Post a Comment