Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Timers;
- namespace GWork
- {
- public class RequestList
- {
- public event Action<RequestMessage> OnRequestMessageAdded = delegate { };
- public event Action<RequestMessage> OnRequestMessageStarted = delegate { };
- public event Action<RequestMessage, ResponseMessage> OnRequestMessageDone = delegate { };
- Dictionary<Guid, RequestMessage> requests;
- public RequestList()
- {
- requests = new Dictionary<Guid, RequestMessage>();
- }
- private void requestWorker_OnRequestMessageStarted(RequestMessage request)
- {
- OnRequestMessageStarted(request);
- }
- private void requestWorker_OnRequestMessageDone(RequestMessage request, ResponseMessage response)
- {
- OnRequestMessageDone(request, response);
- }
- public void Add(RequestMessage request)
- {
- if (request.Timeout <= 0)
- request.Timeout = Timeout.Infinite;
- request.StartDate = DateTime.Now;
- request.Status = MessageStatus.Pending;
- //Create a cancellation token source, this will be used to cancel a task
- request.RequestCancelToken = new CancellationTokenSource();
- requests.Add(request.MessageID, request);
- OnRequestMessageAdded(request);
- RequestWorker requestWorker = new RequestWorker(request);
- //Create and start a task and pass on the cancellation token to it
- try
- {
- requestWorker.OnRequestMessageStarted += new Action<RequestMessage>(requestWorker_OnRequestMessageStarted);
- requestWorker.OnRequestMessageDone += new Action<RequestMessage, ResponseMessage>(requestWorker_OnRequestMessageDone);
- var task = Task.Factory.StartNew(() =>
- //We also pass on the token to the operation for it access the token to check for
- //cancellation
- requestWorker.Process(), request.RequestCancelToken.Token
- //Process(request), request.RequestCancelToken.Token
- );
- task.Wait(request.RequestCancelToken.Token);
- }
- catch (OperationCanceledException)
- {
- }
- finally
- {
- requestWorker.Dispose();
- requestWorker = null;
- }
- }
- public void Cancel(RequestMessage request)
- {
- var dictRequestValue = requests[request.MessageID];
- dictRequestValue.RequestCancelToken.Cancel();
- dictRequestValue.Status = MessageStatus.Cancelled;
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Timers;
- namespace GWork
- {
- public class RequestWorker: IDisposable
- {
- RequestMessage request;
- System.Timers.Timer timerTimeout = null;
- public event Action<RequestMessage> OnRequestMessageStarted = delegate { };
- public event Action<RequestMessage, ResponseMessage> OnRequestMessageDone = delegate { };
- public RequestWorker(RequestMessage request)
- {
- this.request = request;
- }
- public void Dispose()
- {
- if (timerTimeout != null)
- {
- timerTimeout.Dispose();
- timerTimeout = null;
- GC.SuppressFinalize(timerTimeout);
- }
- }
- private void ProcessLogin(CancellationToken token)
- {
- //This simulates work
- var sw = new SpinWait();
- for (var i = 0; i < 1000; i++)
- {
- for (int j = 0; j < 50; j++)
- {
- sw.SpinOnce();
- }
- //This throws an OperationCanceledException if the token has had cancellation requested
- token.ThrowIfCancellationRequested();
- }
- }
- private ResponseMessage ProcessRequest(CancellationToken token)
- {
- ResponseMessage response = new ResponseMessage(request);
- try
- {
- //Check for requested cancellation before processing message
- token.ThrowIfCancellationRequested();
- switch (request.MessageType)
- {
- case RequestMessageType.Login:
- ProcessLogin(token);
- break;
- }
- response.Status = MessageStatus.Done;
- }
- catch (OperationCanceledException)
- {
- response.Status = MessageStatus.Cancelled;
- }
- catch (Exception ex)
- {
- response.Status = MessageStatus.Error;
- response.MessageData = String.Format("Error: {0}. Trace{1}.", ex.Message, ex.StackTrace);
- }
- return response;
- }
- //This method contains the operation being executed by the task in parallel
- public void Process()
- {
- request.Status = MessageStatus.Processing;
- OnRequestMessageStarted(request);
- CancellationToken token = request.RequestCancelToken.Token;
- timerTimeout = new System.Timers.Timer(request.Timeout);
- timerTimeout.AutoReset = false;
- timerTimeout.Elapsed += new ElapsedEventHandler((s, e) =>
- {
- if (request.Status != MessageStatus.Cancelled)
- request.RequestCancelToken.Cancel();
- });
- timerTimeout.Start();
- ResponseMessage response = ProcessRequest(token);
- //This code is reached if the task gets to complete prior to a cancellation request
- request.Status = MessageStatus.Done;
- OnRequestMessageDone(request, response);
- }
- }
- }
Add Comment
Please, Sign In to add comment