Skip to content

Instantly share code, notes, and snippets.

@hanishi
Created July 10, 2013 15:26
Show Gist options
  • Save hanishi/5967246 to your computer and use it in GitHub Desktop.
Save hanishi/5967246 to your computer and use it in GitHub Desktop.
And here is the Synchronizer
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR.Client.Hubs;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace SignalR
{
class Synchronizer : IHubProxy
{
private IHubProxy HubProxy { get; set; }
private State _state;
private readonly AutoResetEvent _auto = new AutoResetEvent(false);
private CancellationTokenSource CancellationTokenSource { get; set; }
internal Synchronizer(IHubProxy hubProxy)
{
HubProxy = hubProxy;
_state = new Paused(this);
CancellationTokenSource = new CancellationTokenSource();
}
public Task Invoke(string method, params object[] args)
{
return _state.Invoke(method, args);
}
public Task<T> Invoke<T>(string method, params object[] args)
{
return _state.Invoke<T>(method, args);
}
public Subscription Subscribe(string eventName)
{
return HubProxy.Subscribe(eventName);
}
public JToken this[string name]
{
get { return HubProxy[name]; }
set { HubProxy[name] = value; }
}
public JsonSerializer JsonSerializer
{
get { return HubProxy.JsonSerializer; }
}
public void Pause()
{
_state.Pause();
}
public void Resume()
{
_state.Resume();
}
public void Stop()
{
_state.Stop();
}
private abstract class State
{
public abstract Task Invoke(string method, params object[] args);
public abstract Task<T> Invoke<T>(string method, params object[] args);
public abstract void Pause();
public abstract void Resume();
public abstract void Stop();
}
private class Resumed : State
{
private Synchronizer Synchronizer { get; set; }
public Resumed(Synchronizer synchronizer)
{
Synchronizer = synchronizer;
}
public override Task Invoke(string method, params object[] args)
{
return Synchronizer.HubProxy.Invoke(method, args);
}
public override Task<T> Invoke<T>(string method, params object[] args)
{
return Synchronizer.HubProxy.Invoke<T>(method, args);
}
public override void Pause()
{
Synchronizer._state = new Paused(Synchronizer);
Console.WriteLine("Paused!");
}
public override void Resume()
{
throw new InvalidOperationException("already resumed");
}
public override void Stop()
{
throw new InvalidOperationException("Pause() before Stop()");
}
}
private class Paused : State
{
private Synchronizer Synchronizer { get; set; }
public Paused(Synchronizer synchronizer)
{
Synchronizer = synchronizer;
}
public override Task Invoke(string method, params object[] args)
{
Console.WriteLine("Invoke Paused!");
Synchronizer._auto.WaitOne();
return Synchronizer.HubProxy.Invoke(method, args);
}
public override Task<T> Invoke<T>(string method, params object[] args)
{
Console.WriteLine("Invoke Paused!");
Synchronizer._auto.WaitOne();
return Synchronizer.HubProxy.Invoke<T>(method, args);
}
public override void Pause()
{
throw new InvalidOperationException("already paused");
}
public override void Resume()
{
Console.WriteLine("Resumed!");
Synchronizer._state = new Resumed(Synchronizer);
Synchronizer._auto.Set();
}
public override void Stop()
{
//Console.WriteLine("Stopped!");
Synchronizer._state = new Stopped(Synchronizer);
Synchronizer._auto.Set();
Synchronizer.CancellationTokenSource.Cancel();
}
}
private class Stopped : State
{
private Synchronizer Synchronizer { get; set; }
private CancellationToken ct;
public Stopped(Synchronizer synchronizer)
{
Synchronizer = synchronizer;
ct = Synchronizer.CancellationTokenSource.Token;
}
public override Task Invoke(string method, params object[] args)
{
for (;;)
{
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
}
}
public override Task<T> Invoke<T>(string method, params object[] args)
{
for (;;)
{
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
}
}
public override void Pause()
{
throw new InvalidOperationException("already stopped");
}
public override void Resume()
{
throw new InvalidOperationException("already stopped");
}
public override void Stop()
{
throw new InvalidOperationException("already stopped");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment