added asynchelper to run task/async method synchronously

Added TransponderUtility Factories and providers to irdaemon.
This commit is contained in:
chris.watts90@outlook.com 2017-06-24 10:26:31 +01:00
parent 17d50b5be1
commit 08b4879526
13 changed files with 248 additions and 19 deletions

View File

@ -1,7 +0,0 @@
namespace Interfaces
{
public interface ITransponderUtilities
{
int GetLastScannedIdAsync();
}
}

View File

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace Interfaces
{
public interface ITransponderUtilityManager
{
List<ITransponderUtilityProvider> GetProviders();
int GetLastScannedId();
}
}

View File

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Interfaces
{
public interface ITransponderUtilityProvider
{
Task<int> GetLastScannedIdAsync();
}
}

View File

@ -2,6 +2,6 @@
{ {
public interface ITransponderUtilityProviderFactory public interface ITransponderUtilityProviderFactory
{ {
ITransponderUtilities GetProvider(); ITransponderUtilityProvider GetProvider();
} }
} }

View File

@ -53,7 +53,8 @@
<Compile Include="ISystemControl.cs" /> <Compile Include="ISystemControl.cs" />
<Compile Include="ISystemControlManager.cs" /> <Compile Include="ISystemControlManager.cs" />
<Compile Include="ISystemControlProviderFactory.cs" /> <Compile Include="ISystemControlProviderFactory.cs" />
<Compile Include="ITransponderUtilities.cs" /> <Compile Include="ITransponderUtilityProvider.cs" />
<Compile Include="ITransponderUtilityManager.cs" />
<Compile Include="ITransponderUtilityProviderFactory.cs" /> <Compile Include="ITransponderUtilityProviderFactory.cs" />
<Compile Include="NotificationEventArgs.cs" /> <Compile Include="NotificationEventArgs.cs" />
<Compile Include="Pilot.cs" /> <Compile Include="Pilot.cs" />

View File

@ -0,0 +1,12 @@
using Interfaces;
namespace IrDaemonNotifier
{
public class IdDaemonTransponderUtilityFactory : ITransponderUtilityProviderFactory
{
public ITransponderUtilityProvider GetProvider()
{
return new IrDaemonTransponderUtilities();
}
}
}

View File

@ -10,12 +10,4 @@ namespace IrDaemonNotifier
Debug.WriteLine("test"); Debug.WriteLine("test");
} }
} }
public class IrDaemonControllerProviderFactory : ISystemControlProviderFactory
{
public ISystemControl GetProvider()
{
return new IrDaemonController();
}
}
} }

View File

@ -40,9 +40,12 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="IdDaemonTransponderUtilityFactory.cs" />
<Compile Include="IrDaemonController.cs" /> <Compile Include="IrDaemonController.cs" />
<Compile Include="IrDaemonControllerProviderFactory.cs" />
<Compile Include="IrDaemonNotifier.cs" /> <Compile Include="IrDaemonNotifier.cs" />
<Compile Include="IrDaemonNotifierProviderFactory.cs" /> <Compile Include="IrDaemonNotifierProviderFactory.cs" />
<Compile Include="IrDaemonTransponderUtilities.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -0,0 +1,13 @@
using System.Threading.Tasks;
using Interfaces;
namespace IrDaemonNotifier
{
public class IrDaemonTransponderUtilities : ITransponderUtilityProvider
{
public Task<int> GetLastScannedIdAsync()
{
return Task.FromResult(-1);
}
}
}

View File

@ -10,6 +10,7 @@ using Ninject;
using RaceLapTimer.Extensions; using RaceLapTimer.Extensions;
using RaceLapTimer.Extensions.Notifications; using RaceLapTimer.Extensions.Notifications;
using RaceLapTimer.Extensions.SystemControl; using RaceLapTimer.Extensions.SystemControl;
using RaceLapTimer.Extensions.TransponderUtilities;
namespace RaceLapTimer namespace RaceLapTimer
{ {
@ -38,9 +39,10 @@ namespace RaceLapTimer
container.Bind<INotifierManager>().To<NotificationManager>().InSingletonScope(); container.Bind<INotifierManager>().To<NotificationManager>().InSingletonScope();
container.Bind<ISystemControlManager>().To<SystemControlManager>().InSingletonScope(); container.Bind<ISystemControlManager>().To<SystemControlManager>().InSingletonScope();
container.Bind<ITransponderUtilityManager>().To<TransponderUtilityManager>().InSingletonScope();
var sM = container.Get<ISystemControlManager>(); var tM = container.Get<ITransponderUtilityManager>();
sM.Shutdown(); tM.GetLastScannedId();
} }
protected override void ConfigureRequestContainer(IKernel container, NancyContext context) protected override void ConfigureRequestContainer(IKernel container, NancyContext context)

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Interfaces;
using RaceLapTimer.Helpers;
namespace RaceLapTimer.Extensions.TransponderUtilities
{
class TransponderUtilityManager:ITransponderUtilityManager
{
private List<ITransponderUtilityProvider> _providers;
private readonly ILoggerService _logger;
public TransponderUtilityManager(ILoggerService logger, IPluginLocator locator)
{
_logger = logger;
RegisterProviders(locator);
}
private void RegisterProviders(IPluginLocator locator)
{
try
{
var providerFactories = locator.Locate<ITransponderUtilityProviderFactory>();
_providers = new List<ITransponderUtilityProvider>();
foreach (var factory in providerFactories)
{
_providers.Add(factory.GetProvider());
}
}
catch (Exception ex)
{
_logger.Error(ex);
}
}
public List<ITransponderUtilityProvider> GetProviders()
{
return _providers;
}
public int GetLastScannedId()
{
//TODO: Implement a utlity provider selector, this can only work with one transponder utility provider.
if (_providers.Any())
{
var provider = _providers.First();
var lastId = AsyncHelpers.RunSync(_providers.First().GetLastScannedIdAsync);
_logger.Trace("Got Id {0} from provider {1}", lastId, provider.GetType().Name);
return lastId;
}
return -1;
}
}
}

View File

@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace RaceLapTimer.Helpers
{
public static class AsyncHelpers
{
/// <summary>
/// Execute's an async Task<T> method which has a void return value synchronously
/// </summary>
/// <param name="task">Task<T> method to execute</param>
public static void RunSync(Func<Task> task)
{
var oldContext = SynchronizationContext.Current;
var synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
synch.Post(async _ =>
{
try
{
await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
}
/// <summary>
/// Execute's an async Task<T> method which has a T return type synchronously
/// </summary>
/// <typeparam name="T">Return Type</typeparam>
/// <param name="task">Task<T> method to execute</param>
/// <returns></returns>
public static T RunSync<T>(Func<Task<T>> task)
{
var oldContext = SynchronizationContext.Current;
var synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
T ret = default(T);
synch.Post(async _ =>
{
try
{
ret = await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
return ret;
}
private class ExclusiveSynchronizationContext : SynchronizationContext
{
private bool done;
public Exception InnerException { get; set; }
readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
readonly Queue<Tuple<SendOrPostCallback, object>> items =
new Queue<Tuple<SendOrPostCallback, object>>();
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("We cannot send to our same thread");
}
public override void Post(SendOrPostCallback d, object state)
{
lock (items)
{
items.Enqueue(Tuple.Create(d, state));
}
workItemsWaiting.Set();
}
public void EndMessageLoop()
{
Post(_ => done = true, null);
}
public void BeginMessageLoop()
{
while (!done)
{
Tuple<SendOrPostCallback, object> task = null;
lock (items)
{
if (items.Count > 0)
{
task = items.Dequeue();
}
}
if (task != null)
{
task.Item1(task.Item2);
if (InnerException != null) // the method threw an exeption
{
throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
}
}
else
{
workItemsWaiting.WaitOne();
}
}
}
public override SynchronizationContext CreateCopy()
{
return this;
}
}
}
}

View File

@ -116,6 +116,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="Extensions\PluginLocator.cs" /> <Compile Include="Extensions\PluginLocator.cs" />
<Compile Include="Extensions\SystemControl\SystemControlManager.cs" /> <Compile Include="Extensions\SystemControl\SystemControlManager.cs" />
<Compile Include="Extensions\TransponderUtilities\TransponderUtilityManager.cs" />
<Compile Include="IDbProvider.cs" /> <Compile Include="IDbProvider.cs" />
<Compile Include="ApiControllers\LapTrackApiModule.cs" /> <Compile Include="ApiControllers\LapTrackApiModule.cs" />
<Compile Include="ApiControllers\MonitorApiModule.cs" /> <Compile Include="ApiControllers\MonitorApiModule.cs" />