H
Harlan Messinger
A few years ago I created an interface, IMonitoredProcess:
public interface IMonitoredProcess
{
event ProgressUpdateHandler ProgressUpdated;
event ProcessStatusHandler ProcessStatusUpdated;
event ProcessEndedHandler Ended;
void Run();
void Cancel(object source, EventArgs e);
int ItemCount { get ; }
}
I created an abstract class, AbstractFileProcessor, that implements
IMonitoredProcess, as a base class for processes that, given a list of
relative file paths, would iterate through them and conduct some
operation on each file with respect to one or two locations where the
files are located (checking that they exist, comparing them between two
locations, copying them from one place to another). The
interface-implementing code in AbstractFileProcessor is:
public event ProgressUpdateHandler ProgressUpdated;
protected void RaiseProgressUpdated(object source,
ProgressUpdateEventArgs e)
{ if (ProgressUpdated != null) ProgressUpdated(source, e); }
public event ProcessStatusHandler ProcessStatusUpdated;
protected void RaiseProcessStatusUpdated(object source,
ProcessStatusEventArgs e)
{
if (ProcessStatusUpdated != null)
ProcessStatusUpdated(source, e);
}
public event ProcessEndedHandler Ended;
protected void RaiseEnded(object source, ProcessEndedEventArgs e)
{if (Ended != null) Ended(source, e); }
public virtual void Cancel(object source, EventArgs e)
{
canceled = true;
}
public virtual void Run()
{
int itemNumber = 0;
ProcessEndType endType = ProcessEndType.Normal;
try
{
foreach (string subpath in fileList)
{
itemNumber++;
RaiseProgressUpdated(
this, new ProgressUpdateEventArgs(this,
ProcessStatus.Running, itemNumber, subpath));
ProcessOneFile(subpath);
if (canceled) break;
}
}
catch(Exception ex)
{
endType = ProcessEndType.Aborted;
RaiseProcessStatusUpdated(
this, new ProcessStatusEventArgs(this,
ProcessStatus.Running, ex.ToString()));
}
finally
{
if (canceled)
endType = ProcessEndType.Canceled;
RaiseEnded(this, new ProcessEndedEventArgs(this, endType));
}
}
Finally, the calling app instantiates one of the classes derived from
AbstractFileProcessor, attaches its Run method to a thread, and kicks
off the thread:
Thread thread = new Thread(new ThreadStart(process.Run));
thread.Start();
I only recently came across the BackgroundWorker class. Now I'm thinking
that I could add to my AbstractFileProcessor class a method that creates
its own thread and hands the object's own Run method to it,
public virtual void Launch()
{
Thread thread = new Thread(new ThreadStart(this.Run));
thread.Start();
}
(and I could even make the Run method private or protected), and then
the application could call Launch directly without needing to create a
thread first--and if I did that, then my AbstractFileProcessor would be
more or less the same thing as a BackgroundWorker. Is that correct?
public interface IMonitoredProcess
{
event ProgressUpdateHandler ProgressUpdated;
event ProcessStatusHandler ProcessStatusUpdated;
event ProcessEndedHandler Ended;
void Run();
void Cancel(object source, EventArgs e);
int ItemCount { get ; }
}
I created an abstract class, AbstractFileProcessor, that implements
IMonitoredProcess, as a base class for processes that, given a list of
relative file paths, would iterate through them and conduct some
operation on each file with respect to one or two locations where the
files are located (checking that they exist, comparing them between two
locations, copying them from one place to another). The
interface-implementing code in AbstractFileProcessor is:
public event ProgressUpdateHandler ProgressUpdated;
protected void RaiseProgressUpdated(object source,
ProgressUpdateEventArgs e)
{ if (ProgressUpdated != null) ProgressUpdated(source, e); }
public event ProcessStatusHandler ProcessStatusUpdated;
protected void RaiseProcessStatusUpdated(object source,
ProcessStatusEventArgs e)
{
if (ProcessStatusUpdated != null)
ProcessStatusUpdated(source, e);
}
public event ProcessEndedHandler Ended;
protected void RaiseEnded(object source, ProcessEndedEventArgs e)
{if (Ended != null) Ended(source, e); }
public virtual void Cancel(object source, EventArgs e)
{
canceled = true;
}
public virtual void Run()
{
int itemNumber = 0;
ProcessEndType endType = ProcessEndType.Normal;
try
{
foreach (string subpath in fileList)
{
itemNumber++;
RaiseProgressUpdated(
this, new ProgressUpdateEventArgs(this,
ProcessStatus.Running, itemNumber, subpath));
ProcessOneFile(subpath);
if (canceled) break;
}
}
catch(Exception ex)
{
endType = ProcessEndType.Aborted;
RaiseProcessStatusUpdated(
this, new ProcessStatusEventArgs(this,
ProcessStatus.Running, ex.ToString()));
}
finally
{
if (canceled)
endType = ProcessEndType.Canceled;
RaiseEnded(this, new ProcessEndedEventArgs(this, endType));
}
}
Finally, the calling app instantiates one of the classes derived from
AbstractFileProcessor, attaches its Run method to a thread, and kicks
off the thread:
Thread thread = new Thread(new ThreadStart(process.Run));
thread.Start();
I only recently came across the BackgroundWorker class. Now I'm thinking
that I could add to my AbstractFileProcessor class a method that creates
its own thread and hands the object's own Run method to it,
public virtual void Launch()
{
Thread thread = new Thread(new ThreadStart(this.Run));
thread.Start();
}
(and I could even make the Run method private or protected), and then
the application could call Launch directly without needing to create a
thread first--and if I did that, then my AbstractFileProcessor would be
more or less the same thing as a BackgroundWorker. Is that correct?