C# Source Code: Using a thread to perform a background task (searching for a file)
[
Home
|
Contents
|
Search
|
Reply
| Previous | Next ]
C# Source Code
Using a thread to perform a background task (searching for a file)
By:
Andrew Baker
Email (spam proof):
Email the originator of this post
Date:
Monday, October 11, 2004
Hits:
4337
Category:
Threading/Asynchronous operations
Article:
Below is an windows form example class, showing how to use a thread to perform a background task. Notice the difference when performing the search on a different thread. The application remains responsive and the user can continue performing other operations. using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Threading; using System.IO; namespace vbUsers.ThreadFileSearch { ///
/// Example form showing how to search for a file using a seperate thread. ///
public class frmThreadFileSearch : System.Windows.Forms.Form { private int _searchesRunning = 0; private System.Windows.Forms.ColumnHeader lvcFileName; private System.Windows.Forms.ColumnHeader lvcLastModified; private System.Windows.Forms.Button btnSearch; private System.Windows.Forms.TextBox txtPath; private System.Windows.Forms.Label lblSearchIn; private System.Windows.Forms.Button btnMultiSearch; private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox txtFilter; private System.Windows.Forms.CheckBox chkSearchDirectories; private System.Windows.Forms.ListView lvFiles; private System.Windows.Forms.Label lblSearchesRunning; ///
/// Required designer variable. ///
private System.ComponentModel.Container components = null; public frmThreadFileSearch() { // // Required for Windows Form Designer support // InitializeComponent(); } ///
/// Clean up any resources being used. ///
protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code ///
/// Required method for Designer support - do not modify /// the contents of this method with the code editor. ///
private void InitializeComponent() { this.lvFiles = new System.Windows.Forms.ListView(); this.lvcFileName = new System.Windows.Forms.ColumnHeader(); this.lvcLastModified = new System.Windows.Forms.ColumnHeader(); this.btnSearch = new System.Windows.Forms.Button(); this.btnMultiSearch = new System.Windows.Forms.Button(); this.txtPath = new System.Windows.Forms.TextBox(); this.lblSearchIn = new System.Windows.Forms.Label(); this.chkSearchDirectories = new System.Windows.Forms.CheckBox(); this.label1 = new System.Windows.Forms.Label(); this.txtFilter = new System.Windows.Forms.TextBox(); this.lblSearchesRunning = new System.Windows.Forms.Label(); this.SuspendLayout(); // // lvFiles // this.lvFiles.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.lvFiles.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.lvcFileName, this.lvcLastModified}); this.lvFiles.FullRowSelect = true; this.lvFiles.HideSelection = false; this.lvFiles.Location = new System.Drawing.Point(8, 38); this.lvFiles.Name = "lvFiles"; this.lvFiles.Size = new System.Drawing.Size(524, 208); this.lvFiles.TabIndex = 0; this.lvFiles.View = System.Windows.Forms.View.Details; // // lvcFileName // this.lvcFileName.Text = "File Name"; this.lvcFileName.Width = 300; // // lvcLastModified // this.lvcLastModified.Text = "Last Modified"; this.lvcLastModified.Width = 180; // // btnSearch // this.btnSearch.Location = new System.Drawing.Point(440, 252); this.btnSearch.Name = "btnSearch"; this.btnSearch.Size = new System.Drawing.Size(92, 31); this.btnSearch.TabIndex = 1; this.btnSearch.Text = "&Search Single Thread..."; this.btnSearch.Click += new System.EventHandler(this.OnSearchClick); // // btnMultiSearch // this.btnMultiSearch.Location = new System.Drawing.Point(344, 252); this.btnMultiSearch.Name = "btnMultiSearch"; this.btnMultiSearch.Size = new System.Drawing.Size(92, 32); this.btnMultiSearch.TabIndex = 2; this.btnMultiSearch.Text = "&Search Multi Thread..."; this.btnMultiSearch.Click += new System.EventHandler(this.OnSearchClick); // // txtPath // this.txtPath.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.txtPath.Location = new System.Drawing.Point(252, 8); this.txtPath.Name = "txtPath"; this.txtPath.Size = new System.Drawing.Size(176, 20); this.txtPath.TabIndex = 3; this.txtPath.Text = "C:\\Temp"; // // lblSearchIn // this.lblSearchIn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.lblSearchIn.Location = new System.Drawing.Point(176, 6); this.lblSearchIn.Name = "lblSearchIn"; this.lblSearchIn.Size = new System.Drawing.Size(72, 24); this.lblSearchIn.TabIndex = 4; this.lblSearchIn.Text = "Search In:"; this.lblSearchIn.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // chkSearchDirectories // this.chkSearchDirectories.Location = new System.Drawing.Point(16, 260); this.chkSearchDirectories.Name = "chkSearchDirectories"; this.chkSearchDirectories.Size = new System.Drawing.Size(156, 20); this.chkSearchDirectories.TabIndex = 5; this.chkSearchDirectories.Text = "Search Sub Directories"; // // label1 // this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.label1.Location = new System.Drawing.Point(432, 6); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(48, 24); this.label1.TabIndex = 7; this.label1.Text = "Filter:"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // txtFilter // this.txtFilter.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.txtFilter.Location = new System.Drawing.Point(480, 8); this.txtFilter.Name = "txtFilter"; this.txtFilter.Size = new System.Drawing.Size(52, 20); this.txtFilter.TabIndex = 6; this.txtFilter.Text = "*.*"; // // lblSearchesRunning // this.lblSearchesRunning.Location = new System.Drawing.Point(12, 8); this.lblSearchesRunning.Name = "lblSearchesRunning"; this.lblSearchesRunning.Size = new System.Drawing.Size(144, 24); this.lblSearchesRunning.TabIndex = 8; this.lblSearchesRunning.Text = "0 searches running..."; this.lblSearchesRunning.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // frmThreadFileSearch // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(540, 289); this.Controls.Add(this.lblSearchesRunning); this.Controls.Add(this.label1); this.Controls.Add(this.txtFilter); this.Controls.Add(this.chkSearchDirectories); this.Controls.Add(this.lblSearchIn); this.Controls.Add(this.txtPath); this.Controls.Add(this.btnMultiSearch); this.Controls.Add(this.btnSearch); this.Controls.Add(this.lvFiles); this.Name = "frmThreadFileSearch"; this.Text = "File Search..."; this.ResumeLayout(false); } #endregion ///
/// The main entry point for the application. ///
[STAThread] static void Main() { Application.Run(new frmThreadFileSearch()); } ///
/// Button click handler (for both buttons) ///
///
///
private void OnSearchClick(object sender, System.EventArgs e) { _searchesRunning++; lblSearchesRunning.Text = _searchesRunning.ToString() + " searches running..."; lock(this) { // Clear the list lvFiles.Items.Clear(); } bool multiThread = false; if ( ((Control)sender).Name == btnMultiSearch.Name ) { // Multi threaded search multiThread = true; } // Create search object FileSearch fs = new FileSearch(txtPath.Text, txtFilter.Text, multiThread, chkSearchDirectories.Checked); fs.Callback += new FileSearch.FinishedSearch(_SearchFinished); fs.Start(); } ///
/// Updates the list of files with the results of the search. /// Callback from FileSearch Class. ///
///
The matching files to add to the list private void _SearchFinished(ArrayList filesFound) { // Lock the form to prevent concurrent access to any UI elements. // NOTE: Should use lvFiles.BeginInvoke(new MethodInvoker(this.UpdateControl); // to marshall back to UI thread. lock(this) { _searchesRunning--; lblSearchesRunning.Text = _searchesRunning.ToString() + " searches running..."; lvFiles.BeginUpdate(); lvFiles.Items.Clear(); foreach ( object file in filesFound ) { FileInfo fi = (FileInfo)file; ListViewItem li = new ListViewItem(); li.Text = fi.FullName; li.SubItems.Add(fi.LastWriteTime.ToString("dd/MMM/yyyy hh:mm:ss")); lvFiles.Items.Add(li); } lvFiles.EndUpdate(); } } #region File Search Class ///
/// File search class ///
internal class FileSearch: IDisposable { #region Delegates and Events public delegate void FinishedSearch(ArrayList filesFound); public FinishedSearch Callback; #endregion #region Private Variables private Thread _thrSearch; private string _path = string.Empty; private string _currentPath = string.Empty; private string _filter = string.Empty; private bool _searchSubdirectories = false; private bool _createThread = false; private ArrayList _files = new ArrayList(100); #endregion #region Constructors public FileSearch(string path, string filter, bool createThread, bool searchSubdirectories) { // Set internal properties _filter = filter; _path = path; _searchSubdirectories = searchSubdirectories; _createThread = createThread; } #endregion #region Public Methods // Start the search public void Start() { // Set the current path _currentPath = _path; if ( _createThread ) { // Call file search in a new thread _thrSearch = new Thread(new ThreadStart(_FileSearch)); _thrSearch.Start(); } else { // Call file search directly _FileSearch(); } } #endregion #region Internal Methods ///
/// Populates an internal array with matching files ///
internal void _FileSearch() { string currentPath = _currentPath; // Get the matching files in this directory DirectoryInfo di = new DirectoryInfo(currentPath); // Return the list of files Array files = di.GetFiles(_filter); // Copy them into our private variable _files.AddRange(files); if( _searchSubdirectories == true) { // Search sub directories foreach(DirectoryInfo subDir in di.GetDirectories()) { _currentPath = subDir.FullName; _FileSearch(); } } // Check if the search has finished if( currentPath == _path && Callback != null ) { // Callback to the form // Could use an asynchronous call back: // Callback.BeginInvoke(_files, null, null); Callback(_files); } #endregion } #region IDisposable Members public void Dispose() { try { if ( _thrSearch != null ) { // Stop the search thread running _thrSearch.Abort(); } } catch { } } #endregion } #endregion } }
Terms and Conditions
Support this site
Download a trial version of the best FTP application on the internet