diff --git a/Documents/Request Framework.txt b/Documents/Request Framework.txt
new file mode 100644
index 0000000..5e9fd6f
--- /dev/null
+++ b/Documents/Request Framework.txt
@@ -0,0 +1,68 @@
+The request framework should not require that .NET multithreading is used for
+asynchronous requests.
+
+Otherwise, it would prvent overlapped operations, 3rd party APIs (eg. used
+via P/Invoke) from being able to use the request framework and possibly even
+spawn duplicate implementations.
+
+
+Design using interfaces:
+
+ interface IWaitable {
+
+ /// Fired when the background process has finished
+ ///
+ /// If the process is already finished when a client registers to this event,
+ /// the registered callback will be invoked synchronously right when the
+ /// registration takes place.
+ ///
+ event EventHandler Finished;
+
+ /// Waits until the background process finishes
+ void Wait();
+
+ /// Waits until the background process finishes or a timeout occurs
+ ///
+ /// Number of milliseconds after which to stop waiting and return immediately
+ ///
+ ///
+ /// True if the background process completed, false if the timeout was reached
+ ///
+ bool Wait(int timeoutMilliseconds);
+
+ /// Whether the background process has finished
+ bool Finished { get; }
+
+ }
+
+ interface IThreadedWaitable : IWaitable {
+
+ WaitHandle WaitHandle { get; }
+
+ }
+
+ interface IRequest : IWaitable {
+
+ ///
+ /// Waits for the background process to complete and re-throws the exception to
+ /// the caller when an error has occured
+ ///
+ void Join();
+
+ }
+
+ interface IRequest : IRequest {
+
+ ///
+ /// Waits for the background process to complete and re-throws the exception to
+ /// the caller when an error has occured
+ ///
+ /// The result of the background processing
+ new ResultType Join();
+
+ }
+
+ interface IThreadedRequest : IRequest, IThreadedWaitable { }
+
+ interface IThreadedRequest :
+ IRequest, IThreadedRequest, IThreadedWaitable { }
diff --git a/Nuclex.Support (x86).csproj b/Nuclex.Support (x86).csproj
index 0a0e8ab..4a0ae00 100644
--- a/Nuclex.Support (x86).csproj
+++ b/Nuclex.Support (x86).csproj
@@ -217,6 +217,7 @@
+
diff --git a/Source/Tracking/Request.cs b/Source/Tracking/Request.cs
index 0477d94..27b9178 100644
--- a/Source/Tracking/Request.cs
+++ b/Source/Tracking/Request.cs
@@ -70,7 +70,7 @@ namespace Nuclex.Support.Tracking {
///
/// A failed request that reports the provided exception as cause for its failure
///
- public static Request CreateFailedDummyRequest(Exception exception) {
+ public static Request CreateFailedDummy(Exception exception) {
return new EndedDummyRequest(exception);
}
@@ -134,7 +134,7 @@ namespace Nuclex.Support.Tracking {
///
/// A failed request that reports the provided exception as cause for its failure
///
- public static new Request CreateFailedDummyRequest(Exception exception) {
+ public static new Request CreateFailedDummy(Exception exception) {
return new EndedDummyRequest(exception);
}
diff --git a/Source/Tracking/Waitable.cs b/Source/Tracking/Waitable.cs
index 69237f4..65cd63b 100644
--- a/Source/Tracking/Waitable.cs
+++ b/Source/Tracking/Waitable.cs
@@ -23,9 +23,7 @@ using System.Threading;
namespace Nuclex.Support.Tracking {
- ///
- /// Base class for actions on which that give an indication of their progress
- ///
+ /// Base class for background processes the user can wait on
///
///
/// By encapsulating long-running operations which will ideally be running in
@@ -40,27 +38,27 @@ namespace Nuclex.Support.Tracking {
/// task has completed. This class deliberately does not provide an Execute()
/// method or anything similar to clearly seperate the initiation of an operation
/// from just monitoring it. By omitting an Execute() method, it also becomes
- /// possible to construct a progression just-in-time when it is explicitely being
+ /// possible to construct a Waitable just-in-time when it is explicitely being
/// asked for.
///
///
public abstract class Waitable {
- #region class EndedDummyProgression
+ #region class EndedDummyWaitable
- /// Dummy progression which always is in the 'ended' state
+ /// Dummy waitable which always is in the 'ended' state
private class EndedDummyWaitable : Waitable {
- /// Initializes a new ended dummy progression
+ /// Initializes a new ended dummy waitable
public EndedDummyWaitable() {
OnAsyncEnded();
}
}
- #endregion // class EndedDummyProgression
+ #endregion // class EndedDummyWaitable
- /// A dummy progression that's always in the 'ended' state
+ /// A dummy waitable that's always in the 'ended' state
///
/// Useful if an operation is already complete when it's being asked for or
/// when a progression that's lazily created is accessed after the original
@@ -68,15 +66,15 @@ namespace Nuclex.Support.Tracking {
///
public static readonly Waitable EndedDummy = new EndedDummyWaitable();
- /// Will be triggered when the progression has ended
+ /// Will be triggered when the Waitable has ended
public event EventHandler AsyncEnded;
- /// Whether the progression has ended already
+ /// Whether the Waitable has ended already
public bool Ended {
get { return this.ended; }
}
- /// WaitHandle that can be used to wait for the progression to end
+ /// WaitHandle that can be used to wait for the Waitable to end
public WaitHandle WaitHandle {
get {
@@ -87,11 +85,11 @@ namespace Nuclex.Support.Tracking {
// We can *not* optimize this lock away since we absolutely must not create
// two doneEvents -- someone might call .WaitOne() on the first one when only
// the second one is referenced by this.doneEvent and thus gets set in the end.
- if (this.doneEvent == null) {
+ if(this.doneEvent == null) {
- lock (this) {
+ lock(this) {
- if (this.doneEvent == null)
+ if(this.doneEvent == null)
this.doneEvent = new ManualResetEvent(this.ended);
}
@@ -121,13 +119,13 @@ namespace Nuclex.Support.Tracking {
// Make sure the progression is not ended more than once. By guaranteeing that
// a progression can only be ended once, we allow users of this class to
// skip some safeguards against notifications arriving twice.
- lock (this) {
+ lock(this) {
// No double lock here, this is an exception that indicates an implementation
// error that will not be triggered under normal circumstances. We don't want
// to waste any effort optimizing the speed at which an implementation fault
// will be noticed.
- if (this.ended)
+ if(this.ended)
throw new InvalidOperationException("The progression has already been ended");
this.ended = true;
@@ -137,12 +135,12 @@ namespace Nuclex.Support.Tracking {
// Doesn't need a lock. If another thread wins the race and creates the event
// after we just saw it being null, it would be created in an already set
// state due to the ended flag (see above) being set to true beforehand!
- if (this.doneEvent != null)
+ if(this.doneEvent != null)
this.doneEvent.Set();
// Finally, fire the AsyncEnded event
EventHandler copy = AsyncEnded;
- if (copy != null)
+ if(copy != null)
copy(this, EventArgs.Empty);
}