mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-15 11:48:09 +00:00
Refactored MtApiService: command will be executed in first expert will be invoked by quote tick
This commit is contained in:
@@ -1,15 +1,8 @@
|
|||||||
using System;
|
namespace MTApiService
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace MTApiService
|
|
||||||
{
|
{
|
||||||
public interface ICommandManager
|
public interface ICommandManager
|
||||||
{
|
{
|
||||||
void EnqueueCommand(MtCommand command);
|
void EnqueueCommandTask(MtCommandTask task);
|
||||||
MtCommand DequeueCommand();
|
MtCommandTask DequeueCommandTask();
|
||||||
|
|
||||||
void OnCommandExecuted(MtExpert expert, MtCommand command, MtResponse response);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@
|
|||||||
<Compile Include="IMtApiServer.cs" />
|
<Compile Include="IMtApiServer.cs" />
|
||||||
<Compile Include="MtApiProxy.cs" />
|
<Compile Include="MtApiProxy.cs" />
|
||||||
<Compile Include="MtClient.cs" />
|
<Compile Include="MtClient.cs" />
|
||||||
|
<Compile Include="MtCommandTask.cs" />
|
||||||
<Compile Include="MtMqlBookInfo.cs" />
|
<Compile Include="MtMqlBookInfo.cs" />
|
||||||
<Compile Include="MtMqlRates.cs" />
|
<Compile Include="MtMqlRates.cs" />
|
||||||
<Compile Include="MtMqlTick.cs" />
|
<Compile Include="MtMqlTick.cs" />
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace MTApiService
|
||||||
|
{
|
||||||
|
public class MtCommandTask
|
||||||
|
{
|
||||||
|
private readonly EventWaitHandle _responseWaiter = new AutoResetEvent(false);
|
||||||
|
private MtResponse _result;
|
||||||
|
private readonly object _locker = new object();
|
||||||
|
|
||||||
|
public MtCommandTask(MtCommand command)
|
||||||
|
{
|
||||||
|
Command = command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MtCommand Command { get; private set; }
|
||||||
|
|
||||||
|
public MtResponse WaitResult(int time)
|
||||||
|
{
|
||||||
|
_responseWaiter.WaitOne(time);
|
||||||
|
lock (_locker)
|
||||||
|
{
|
||||||
|
return _result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetResult(MtResponse result)
|
||||||
|
{
|
||||||
|
lock (_locker)
|
||||||
|
{
|
||||||
|
_result = result;
|
||||||
|
}
|
||||||
|
_responseWaiter.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace MTApiService
|
namespace MTApiService
|
||||||
{
|
{
|
||||||
class MtCommandExecutorManager : ICommandManager
|
internal class MtCommandExecutorManager : ICommandManager
|
||||||
{
|
{
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
@@ -14,8 +11,8 @@ namespace MTApiService
|
|||||||
{
|
{
|
||||||
lock (_locker)
|
lock (_locker)
|
||||||
{
|
{
|
||||||
mCommandExecutors.Clear();
|
_commandExecutors.Clear();
|
||||||
mCommands.Clear();
|
_commandTasks.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,26 +21,26 @@ namespace MTApiService
|
|||||||
if (commandExecutor == null)
|
if (commandExecutor == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var notify = false;
|
||||||
lock (_locker)
|
lock (_locker)
|
||||||
{
|
{
|
||||||
if (mCommandExecutors.Contains(commandExecutor) == true)
|
if (_commandExecutors.Contains(commandExecutor))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mCommandExecutors.Add(commandExecutor);
|
_commandExecutors.Add(commandExecutor);
|
||||||
|
if (_commandTasks.Count > 0)
|
||||||
commandExecutor.CommandManager = this;
|
|
||||||
|
|
||||||
if (mCurrentExecutor == null)
|
|
||||||
{
|
{
|
||||||
mCurrentExecutor = commandExecutor;
|
notify = true;
|
||||||
mCurrentExecutor.IsCommandExecutor = true;
|
|
||||||
|
|
||||||
if (mCommands.Count > 0)
|
|
||||||
{
|
|
||||||
mCurrentExecutor.NotifyCommandReady();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commandExecutor.CommandExecuted += CommandExecutor_CommandExecuted;
|
||||||
|
commandExecutor.CommandManager = this;
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
{
|
||||||
|
NotifyCommandReady();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveCommandExecutor(MtExpert commandExecutor)
|
public void RemoveCommandExecutor(MtExpert commandExecutor)
|
||||||
@@ -51,80 +48,88 @@ namespace MTApiService
|
|||||||
if (commandExecutor == null)
|
if (commandExecutor == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var notify = false;
|
||||||
lock (_locker)
|
lock (_locker)
|
||||||
{
|
{
|
||||||
if (mCommandExecutors.Contains(commandExecutor) == false)
|
if (_commandExecutors.Contains(commandExecutor) == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mCommandExecutors.Remove(commandExecutor);
|
_commandExecutors.Remove(commandExecutor);
|
||||||
|
if (_commandTasks.Count > 0)
|
||||||
if (mCurrentExecutor == commandExecutor)
|
|
||||||
{
|
{
|
||||||
mCurrentExecutor.IsCommandExecutor = false;
|
notify = true;
|
||||||
mCurrentExecutor = mCommandExecutors.Count > 0 ? mCommandExecutors[0] : null;
|
|
||||||
|
|
||||||
if (mCommands.Count > 0)
|
|
||||||
{
|
|
||||||
mCurrentExecutor.NotifyCommandReady();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commandExecutor.CommandExecuted -= CommandExecutor_CommandExecuted;
|
||||||
|
commandExecutor.CommandManager = null;
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
{
|
||||||
|
NotifyCommandReady();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnqueueCommand(MtCommand command)
|
public void EnqueueCommandTask(MtCommandTask task)
|
||||||
{
|
{
|
||||||
if (command == null)
|
if (task == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (_locker)
|
lock (_locker)
|
||||||
{
|
{
|
||||||
mCommands.Enqueue(command);
|
_commandTasks.Enqueue(task);
|
||||||
|
|
||||||
mCurrentExecutor.NotifyCommandReady();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotifyCommandReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MtCommand DequeueCommand()
|
public MtCommandTask DequeueCommandTask()
|
||||||
{
|
{
|
||||||
lock (_locker)
|
lock (_locker)
|
||||||
{
|
{
|
||||||
return mCommands.Count > 0 ? mCommands.Dequeue() : null;
|
return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCommandExecuted(MtExpert expert, MtCommand command, MtResponse response)
|
|
||||||
{
|
|
||||||
if (expert == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (CommandExecuted != null)
|
|
||||||
{
|
|
||||||
CommandExecuted(this, new MtCommandExecuteEventArgs(command, response));
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_locker)
|
|
||||||
{
|
|
||||||
if (expert == mCurrentExecutor)
|
|
||||||
{
|
|
||||||
if (mCommands.Count > 0)
|
|
||||||
{
|
|
||||||
mCurrentExecutor.NotifyCommandReady();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Events
|
#region Private Methods
|
||||||
public event EventHandler<MtCommandExecuteEventArgs> CommandExecuted;
|
private void NotifyCommandReady()
|
||||||
|
{
|
||||||
|
var commandExecutors = new List<MtExpert>();
|
||||||
|
lock (_locker)
|
||||||
|
{
|
||||||
|
commandExecutors.AddRange(_commandExecutors);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var executor in commandExecutors)
|
||||||
|
{
|
||||||
|
executor.NotifyCommandReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CommandExecutor_CommandExecuted(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var notify = false;
|
||||||
|
lock (_locker)
|
||||||
|
{
|
||||||
|
if (_commandTasks.Count > 0)
|
||||||
|
{
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
{
|
||||||
|
NotifyCommandReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
private MtExpert mCurrentExecutor;
|
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
|
||||||
|
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
|
||||||
private List<MtExpert> mCommandExecutors = new List<MtExpert>();
|
|
||||||
private Queue<MtCommand> mCommands = new Queue<MtCommand>();
|
|
||||||
|
|
||||||
private readonly object _locker = new object();
|
private readonly object _locker = new object();
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
+71
-52
@@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace MTApiService
|
namespace MTApiService
|
||||||
{
|
{
|
||||||
@@ -10,43 +7,46 @@ namespace MTApiService
|
|||||||
public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote);
|
public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote);
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
private MtQuote _Quote;
|
private MtQuote _quote;
|
||||||
public MtQuote Quote
|
public MtQuote Quote
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
lock (_locker)
|
lock (_locker)
|
||||||
{
|
{
|
||||||
return _Quote;
|
return _quote;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
lock(_locker)
|
lock(_locker)
|
||||||
{
|
{
|
||||||
_Quote = value;
|
_quote = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QuoteChanged != null)
|
FireOnQuoteChanged(value);
|
||||||
{
|
|
||||||
QuoteChanged(this, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Handle { get; private set; }
|
public int Handle { get; private set; }
|
||||||
|
|
||||||
private volatile bool _IsEnable = true;
|
private bool _isEnable = true;
|
||||||
public bool IsEnable
|
public bool IsEnable
|
||||||
{
|
{
|
||||||
get { return _IsEnable; }
|
get
|
||||||
private set { _IsEnable = value; }
|
{
|
||||||
}
|
lock (_locker)
|
||||||
|
{
|
||||||
private volatile bool _IsCommandExecutor = true;
|
return _isEnable;
|
||||||
public bool IsCommandExecutor
|
}
|
||||||
{
|
}
|
||||||
get { return _IsCommandExecutor; }
|
private set
|
||||||
set { _IsCommandExecutor = value; }
|
{
|
||||||
|
lock (_locker)
|
||||||
|
{
|
||||||
|
_isEnable = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICommandManager CommandManager
|
public ICommandManager CommandManager
|
||||||
@@ -55,14 +55,14 @@ namespace MTApiService
|
|||||||
{
|
{
|
||||||
lock (_locker)
|
lock (_locker)
|
||||||
{
|
{
|
||||||
return mCommandManager;
|
return _commandManager;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
lock (_locker)
|
lock (_locker)
|
||||||
{
|
{
|
||||||
mCommandManager = value;
|
_commandManager = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,51 +73,43 @@ namespace MTApiService
|
|||||||
{
|
{
|
||||||
Quote = quote;
|
Quote = quote;
|
||||||
Handle = handle;
|
Handle = handle;
|
||||||
mMtHadler = mtHandler;
|
_mtHadler = mtHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Deinit()
|
public void Deinit()
|
||||||
{
|
{
|
||||||
IsEnable = false;
|
IsEnable = false;
|
||||||
|
FireOnDeinited();
|
||||||
if (Deinited != null)
|
|
||||||
{
|
|
||||||
Deinited(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendResponse(MtResponse response)
|
public void SendResponse(MtResponse response)
|
||||||
{
|
{
|
||||||
MtCommand command = mCommand;
|
_commandTask.SetResult(response);
|
||||||
mCommand = null;
|
_commandTask = null;
|
||||||
|
FireOnCommandExecuted();
|
||||||
ICommandManager commandManager = CommandManager;
|
|
||||||
if (commandManager != null)
|
|
||||||
{
|
|
||||||
commandManager.OnCommandExecuted(this, command, response);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetCommandType()
|
public int GetCommandType()
|
||||||
{
|
{
|
||||||
if (IsCommandExecutor)
|
var commandManager = CommandManager;
|
||||||
|
if (commandManager != null)
|
||||||
{
|
{
|
||||||
ICommandManager commandManager = CommandManager;
|
_commandTask = commandManager.DequeueCommandTask();
|
||||||
if (mCommandManager != null)
|
|
||||||
{
|
|
||||||
mCommand = mCommandManager.DequeueCommand();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mCommand != null ? mCommand.CommandType : 0;
|
return _commandTask != null && _commandTask.Command != null ? _commandTask.Command.CommandType : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object GetCommandParameter(int index)
|
public object GetCommandParameter(int index)
|
||||||
{
|
{
|
||||||
if (mCommand != null && mCommand.Parameters != null
|
if (_commandTask != null)
|
||||||
&& index >= 0 && index < mCommand.Parameters.Count)
|
|
||||||
{
|
{
|
||||||
return mCommand.Parameters[index];
|
var command = _commandTask.Command;
|
||||||
|
if (command != null && command.Parameters != null
|
||||||
|
&& index >= 0 && index < command.Parameters.Count)
|
||||||
|
{
|
||||||
|
return command.Parameters[index];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -131,13 +123,39 @@ namespace MTApiService
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
private void SendTickToMetaTrader()
|
private void SendTickToMetaTrader()
|
||||||
{
|
{
|
||||||
if (mMtHadler != null)
|
if (_mtHadler != null)
|
||||||
{
|
{
|
||||||
mMtHadler.SendTickToMetaTrader(Handle);
|
_mtHadler.SendTickToMetaTrader(Handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FireOnQuoteChanged(MtQuote quote)
|
||||||
|
{
|
||||||
|
var handler = QuoteChanged;
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
handler(this, quote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FireOnDeinited()
|
||||||
|
{
|
||||||
|
var handler = Deinited;
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
handler(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FireOnCommandExecuted()
|
||||||
|
{
|
||||||
|
var handler = CommandExecuted;
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
handler(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -145,12 +163,13 @@ namespace MTApiService
|
|||||||
#region Events
|
#region Events
|
||||||
public event EventHandler Deinited;
|
public event EventHandler Deinited;
|
||||||
public event MtQuoteHandler QuoteChanged;
|
public event MtQuoteHandler QuoteChanged;
|
||||||
|
public event EventHandler CommandExecuted;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
private readonly IMetaTraderHandler mMtHadler;
|
private readonly IMetaTraderHandler _mtHadler;
|
||||||
private MtCommand mCommand;
|
private MtCommandTask _commandTask;
|
||||||
private ICommandManager mCommandManager;
|
private ICommandManager _commandManager;
|
||||||
private readonly object _locker = new object();
|
private readonly object _locker = new object();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-117
@@ -1,18 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.ServiceModel;
|
using System.ServiceModel;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.ServiceModel.Channels;
|
using System.ServiceModel.Channels;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
||||||
namespace MTApiService
|
namespace MTApiService
|
||||||
{
|
{
|
||||||
class MtServer : IDisposable, IMtApiServer
|
internal class MtServer : IDisposable, IMtApiServer
|
||||||
{
|
{
|
||||||
#region Constants
|
#region Constants
|
||||||
private const int WAIT_RESPONSE_TIME = 40000; // 40 sec
|
private const int WAIT_RESPONSE_TIME = 40000; // 40 sec
|
||||||
@@ -23,12 +20,7 @@ namespace MTApiService
|
|||||||
public MtServer(int port)
|
public MtServer(int port)
|
||||||
{
|
{
|
||||||
Port = port;
|
Port = port;
|
||||||
mService = new MtService(this);
|
_service = new MtService(this);
|
||||||
|
|
||||||
mHosts = new List<ServiceHost>();
|
|
||||||
|
|
||||||
mExecutorManager = new MtCommandExecutorManager();
|
|
||||||
mExecutorManager.CommandExecuted += mExecutorManager_CommandExecuted;
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -39,21 +31,18 @@ namespace MTApiService
|
|||||||
#region Public Methods
|
#region Public Methods
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
bool hostsInitialized = InitHosts(Port);
|
var hostsInitialized = InitHosts(Port);
|
||||||
if (hostsInitialized == false)
|
if (hostsInitialized == false)
|
||||||
return;
|
|
||||||
|
|
||||||
lock (mExpertsLocker)
|
|
||||||
{
|
{
|
||||||
mExperts = new List<MtExpert>();
|
Debug.WriteLine("Start: InitHosts failed. ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool InitHosts(int port)
|
private bool InitHosts(int port)
|
||||||
{
|
{
|
||||||
lock (mHostLocker)
|
lock (_hosts)
|
||||||
{
|
{
|
||||||
if (mHosts.Count > 0)
|
if (_hosts.Count > 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//init local pipe host
|
//init local pipe host
|
||||||
@@ -61,7 +50,7 @@ namespace MTApiService
|
|||||||
ServiceHost localServiceHost = CreateServiceHost(localUrl, true);
|
ServiceHost localServiceHost = CreateServiceHost(localUrl, true);
|
||||||
if (localServiceHost != null)
|
if (localServiceHost != null)
|
||||||
{
|
{
|
||||||
mHosts.Add(localServiceHost);
|
_hosts.Add(localServiceHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
//init network hosts
|
//init network hosts
|
||||||
@@ -79,7 +68,7 @@ namespace MTApiService
|
|||||||
ServiceHost serviceHost = CreateServiceHost(networkUrl, false);
|
ServiceHost serviceHost = CreateServiceHost(networkUrl, false);
|
||||||
if (serviceHost != null)
|
if (serviceHost != null)
|
||||||
{
|
{
|
||||||
mHosts.Add(serviceHost);
|
_hosts.Add(serviceHost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,8 +86,8 @@ namespace MTApiService
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
serviceHost = new ServiceHost(mService);
|
serviceHost = new ServiceHost(_service);
|
||||||
Binding binding = CreateConnectionBinding(local);
|
var binding = CreateConnectionBinding(local);
|
||||||
|
|
||||||
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress);
|
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress);
|
||||||
serviceHost.Open();
|
serviceHost.Open();
|
||||||
@@ -116,17 +105,17 @@ namespace MTApiService
|
|||||||
{
|
{
|
||||||
if (expert != null)
|
if (expert != null)
|
||||||
{
|
{
|
||||||
expert.Deinited += new EventHandler(expert_Deinited);
|
expert.Deinited += expert_Deinited;
|
||||||
expert.QuoteChanged += new MtExpert.MtQuoteHandler(expert_QuoteChanged);
|
expert.QuoteChanged += expert_QuoteChanged;
|
||||||
|
|
||||||
lock (mExpertsLocker)
|
lock (_experts)
|
||||||
{
|
{
|
||||||
mExperts.Add(expert);
|
_experts.Add(expert);
|
||||||
}
|
}
|
||||||
|
|
||||||
mExecutorManager.AddCommandExecutor(expert);
|
_executorManager.AddCommandExecutor(expert);
|
||||||
|
|
||||||
mService.OnQuoteAdded(expert.Quote);
|
_service.OnQuoteAdded(expert.Quote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,31 +129,11 @@ namespace MTApiService
|
|||||||
|
|
||||||
if (command != null)
|
if (command != null)
|
||||||
{
|
{
|
||||||
EventWaitHandle responseWaiter = new AutoResetEvent(false);
|
var task = new MtCommandTask(command);
|
||||||
|
_executorManager.EnqueueCommandTask(task);
|
||||||
lock (mResponseLocker)
|
|
||||||
{
|
|
||||||
mResponseWaiters[command] = responseWaiter;
|
|
||||||
}
|
|
||||||
|
|
||||||
mExecutorManager.EnqueueCommand(command);
|
|
||||||
|
|
||||||
//wait for execute command in MetaTrader
|
//wait for execute command in MetaTrader
|
||||||
responseWaiter.WaitOne(WAIT_RESPONSE_TIME);
|
response = task.WaitResult(WAIT_RESPONSE_TIME);
|
||||||
|
|
||||||
lock (mResponseLocker)
|
|
||||||
{
|
|
||||||
if (mResponseWaiters.ContainsKey(command) == true)
|
|
||||||
{
|
|
||||||
mResponseWaiters.Remove(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mResponses.ContainsKey(command) == true)
|
|
||||||
{
|
|
||||||
response = mResponses[command];
|
|
||||||
mResponses.Remove(command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
@@ -172,9 +141,9 @@ namespace MTApiService
|
|||||||
|
|
||||||
public IEnumerable<MtQuote> GetQuotes()
|
public IEnumerable<MtQuote> GetQuotes()
|
||||||
{
|
{
|
||||||
lock (mExpertsLocker)
|
lock (_experts)
|
||||||
{
|
{
|
||||||
return (from s in mExperts select s.Quote);
|
return (from s in _experts select s.Quote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,23 +152,26 @@ namespace MTApiService
|
|||||||
#region Private Methods
|
#region Private Methods
|
||||||
private void stopTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
private void stopTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
int expertsCount = 0;
|
var expertsCount = 0;
|
||||||
|
|
||||||
lock (mExpertsLocker)
|
lock (_experts)
|
||||||
{
|
{
|
||||||
expertsCount = mExperts.Count();
|
expertsCount = _experts.Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expertsCount == 0)
|
if (expertsCount == 0)
|
||||||
{
|
{
|
||||||
mService.OnStopServer();
|
_service.OnStopServer();
|
||||||
|
|
||||||
stop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
var stopTimer = sender as System.Timers.Timer;
|
var stopTimer = sender as System.Timers.Timer;
|
||||||
stopTimer.Stop();
|
if (stopTimer != null)
|
||||||
stopTimer.Elapsed -= stopTimer_Elapsed;
|
{
|
||||||
|
stopTimer.Stop();
|
||||||
|
stopTimer.Elapsed -= stopTimer_Elapsed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CreateConnectionAddress(string host, int port, bool local)
|
private string CreateConnectionAddress(string host, int port, bool local)
|
||||||
@@ -265,65 +237,62 @@ namespace MTApiService
|
|||||||
return connectionBinding;
|
return connectionBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stop()
|
private void Stop()
|
||||||
{
|
{
|
||||||
mExecutorManager.Stop();
|
_executorManager.Stop();
|
||||||
|
|
||||||
lock (mHostLocker)
|
lock (_hosts)
|
||||||
{
|
{
|
||||||
if (mHosts.Count == 0)
|
if (_hosts.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (var host in mHosts)
|
foreach (var host in _hosts)
|
||||||
{
|
{
|
||||||
host.Close();
|
host.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (TimeoutException)
|
catch (TimeoutException)
|
||||||
{
|
{
|
||||||
foreach (var host in mHosts)
|
foreach (var host in _hosts)
|
||||||
{
|
{
|
||||||
host.Abort();
|
host.Abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
// ignored
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
mHosts.Clear();
|
_hosts.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Stopped != null)
|
FireOnStopped();
|
||||||
{
|
|
||||||
Stopped(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expert_Deinited(object sender, EventArgs e)
|
private void expert_Deinited(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
MtExpert expert = (MtExpert)sender;
|
if (sender == null)
|
||||||
int expertsCount = 0;
|
return;
|
||||||
|
|
||||||
lock (mExpertsLocker)
|
var expert = (MtExpert)sender;
|
||||||
|
var expertsCount = 0;
|
||||||
|
|
||||||
|
lock (_experts)
|
||||||
{
|
{
|
||||||
mExperts.Remove(expert);
|
_experts.Remove(expert);
|
||||||
|
expertsCount = _experts.Count();
|
||||||
expertsCount = mExperts.Count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mExecutorManager.RemoveCommandExecutor(expert);
|
_executorManager.RemoveCommandExecutor(expert);
|
||||||
|
|
||||||
if (expert != null)
|
expert.Deinited -= expert_Deinited;
|
||||||
{
|
expert.QuoteChanged -= expert_QuoteChanged;
|
||||||
expert.Deinited -= expert_Deinited;
|
|
||||||
expert.QuoteChanged -= expert_QuoteChanged;
|
|
||||||
|
|
||||||
mService.OnQuoteRemoved(expert.Quote);
|
_service.OnQuoteRemoved(expert.Quote);
|
||||||
}
|
|
||||||
|
|
||||||
if (expertsCount == 0)
|
if (expertsCount == 0)
|
||||||
{
|
{
|
||||||
@@ -334,28 +303,18 @@ namespace MTApiService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mExecutorManager_CommandExecuted(object sender, MtCommandExecuteEventArgs e)
|
|
||||||
{
|
|
||||||
EventWaitHandle responseWaiter = null;
|
|
||||||
|
|
||||||
lock (mResponseLocker)
|
|
||||||
{
|
|
||||||
if (mResponseWaiters.ContainsKey(e.Command) == true)
|
|
||||||
{
|
|
||||||
responseWaiter = mResponseWaiters[e.Command];
|
|
||||||
mResponses[e.Command] = e.Response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (responseWaiter != null)
|
|
||||||
{
|
|
||||||
responseWaiter.Set();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expert_QuoteChanged(MtExpert expert, MtQuote quote)
|
private void expert_QuoteChanged(MtExpert expert, MtQuote quote)
|
||||||
{
|
{
|
||||||
mService.QuoteUpdate(quote);
|
_service.QuoteUpdate(quote);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FireOnStopped()
|
||||||
|
{
|
||||||
|
var handler = Stopped;
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
handler(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -367,25 +326,16 @@ namespace MTApiService
|
|||||||
#region IDispose
|
#region IDispose
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
stop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Fields
|
#region Fields
|
||||||
private readonly MtService mService;
|
private readonly MtService _service;
|
||||||
private readonly List<ServiceHost> mHosts;
|
private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
|
||||||
|
private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager();
|
||||||
private readonly MtCommandExecutorManager mExecutorManager;
|
private readonly List<MtExpert> _experts = new List<MtExpert>();
|
||||||
private List<MtExpert> mExperts;
|
|
||||||
|
|
||||||
private readonly Dictionary<MtCommand, EventWaitHandle> mResponseWaiters = new Dictionary<MtCommand, EventWaitHandle>();
|
|
||||||
private readonly Dictionary<MtCommand, MtResponse> mResponses = new Dictionary<MtCommand, MtResponse>();
|
|
||||||
|
|
||||||
private readonly object mResponseLocker = new object();
|
|
||||||
private readonly object mHostLocker = new object();
|
|
||||||
private readonly object mExpertsLocker = new object();
|
|
||||||
private readonly object mCommandExecutorsLocker = new object();
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user