I had nothing to do so I wrote a quick example to help you utilize the AsyncResult pattern as well as locking.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections;
namespace CodeProjectHelpProject
{
class Program
{
class OperatingException : Exception
{
public OperatingException(string ex) : base(ex) { }
public OperatingException(string ex, Exception innerEx) : base(ex, innerEx) { }
}
class OperationManager
{
public readonly SortedDictionary<datetime,> ResultHistory = new SortedDictionary<datetime,>();
public OperationResult CurrentOperation { get; private set; }
public void Begin(OperationResult newOperation, bool cancelExisting = false, WaitCallback resumePoint = null)
{
if (CurrentOperation != null && !cancelExisting) throw new OperatingException("The Operation Manager does not support multiple operations and there is currently an operation pending");
else
{
lock (this)
{
lock (CurrentOperation)
{
if (CurrentOperation != null && !CurrentOperation.Signal)
{
CurrentOperation.Cancel();
}
}
AddHistoryResult(CurrentOperation);
CurrentOperation = newOperation;
try
{
CurrentOperation.Begin();
}
catch
{
if (resumePoint != null)
{
AddHistoryResult(newOperation);
resumePoint.Invoke(CurrentOperation);
CurrentOperation = null;
}
}
}
}
}
private void AddHistoryResult(OperationResult what, DateTime? when = null)
{
if (what == null) return;
try
{
when = when ?? DateTime.UtcNow;
IDictionary securePointer = ResultHistory;
lock (securePointer.SyncRoot)
{
ResultHistory.Add(when.Value, what);
}
securePointer = null;
}
catch
{
throw;
}
}
}
sealed class OperationResult : IAsyncResult
{
private OperationManager manager;
public OperationResult(OperationManager manager)
{
this.manager = manager;
}
public bool Signal { get; set; }
internal void Cancel()
{
lock (this)
{
this.Signal = true;
}
}
internal void Begin()
{
lock (this)
{
if (this.Signal) return;
else
{
try
{
new Thread(() =>
{
this.Signal = true;
return;
}).Start();
}
catch(Exception ex)
{
PropagateException(ex);
}
}
}
}
private void PropagateException(Exception ex)
{
throw new OperatingException("An exception occured", ex);
}
public object AsyncState
{
get { throw new NotImplementedException(); }
}
public WaitHandle AsyncWaitHandle
{
get { throw new NotImplementedException(); }
}
public bool CompletedSynchronously
{
get { throw new NotImplementedException(); }
}
public bool IsCompleted
{
get { return !Signal; }
}
}
static void OnCancel(object parameter)
{
}
static void AfterProcessing(IAsyncResult result)
{
}
static void Main(string[] args)
{
OperationManager manager = new OperationManager();
WaitCallback resumePoint = new WaitCallback(OnCancel);
var result = new OperationResult(manager);
manager.Begin(result, false, resumePoint);
ThreadPriority oldPriority = Thread.CurrentThread.Priority;
while (result.Signal)
{
Thread.CurrentThread.Priority = ThreadPriority.Lowest;
Thread.SpinWait((int)DateTime.Now.Ticks / DateTime.UtcNow.Year);
}
Thread.CurrentThread.Priority = oldPriority;
AfterProcessing(result);
}
}
}
Let me know how you like it!
It is not 100% complete but it should provide you a suitable base to construct a properly synchronized design pattern.
For instance one thing I would do is utilize the ThreadPool rather than Threads due to the intrinsic memory overhead of creating threads however your external code may require thread local storage and I can see how this may be beneficial due to how old code using fast calls are executed.
Another would be to move the resumePoint to the OperationResult and then invocate it from the Begin or any other Method when required. Right now there is separation which I have purposefully done because I want you to learn a thing or two as you work with the code.
There is a lot being shown in the example and if you have further questions you know exactly where to ask them!
Sincerely,
V//