diff --git a/MTApiService/ICommandManager.cs b/MTApiService/ICommandManager.cs index 7f9d3eb2..2db3b80b 100755 --- a/MTApiService/ICommandManager.cs +++ b/MTApiService/ICommandManager.cs @@ -1,15 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MTApiService +namespace MTApiService { public interface ICommandManager { - void EnqueueCommand(MtCommand command); - MtCommand DequeueCommand(); - - void OnCommandExecuted(MtExpert expert, MtCommand command, MtResponse response); + void EnqueueCommandTask(MtCommandTask task); + MtCommandTask DequeueCommandTask(); } } diff --git a/MTApiService/MTApiService.csproj b/MTApiService/MTApiService.csproj index 7e85c90d..44777da8 100755 --- a/MTApiService/MTApiService.csproj +++ b/MTApiService/MTApiService.csproj @@ -59,6 +59,7 @@ + diff --git a/MTApiService/MtCommandTask.cs b/MTApiService/MtCommandTask.cs new file mode 100644 index 00000000..bf151e99 --- /dev/null +++ b/MTApiService/MtCommandTask.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(); + } + + } +} \ No newline at end of file diff --git a/MTApiService/MtExecutorManager.cs b/MTApiService/MtExecutorManager.cs index 3e8d9f89..d73b0a2e 100755 --- a/MTApiService/MtExecutorManager.cs +++ b/MTApiService/MtExecutorManager.cs @@ -1,12 +1,9 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; namespace MTApiService { - class MtCommandExecutorManager : ICommandManager + internal class MtCommandExecutorManager : ICommandManager { #region Public Methods @@ -14,8 +11,8 @@ namespace MTApiService { lock (_locker) { - mCommandExecutors.Clear(); - mCommands.Clear(); + _commandExecutors.Clear(); + _commandTasks.Clear(); } } @@ -24,26 +21,26 @@ namespace MTApiService if (commandExecutor == null) return; + var notify = false; lock (_locker) { - if (mCommandExecutors.Contains(commandExecutor) == true) + if (_commandExecutors.Contains(commandExecutor)) return; - mCommandExecutors.Add(commandExecutor); - - commandExecutor.CommandManager = this; - - if (mCurrentExecutor == null) + _commandExecutors.Add(commandExecutor); + if (_commandTasks.Count > 0) { - mCurrentExecutor = commandExecutor; - mCurrentExecutor.IsCommandExecutor = true; - - if (mCommands.Count > 0) - { - mCurrentExecutor.NotifyCommandReady(); - } + notify = true; } } + + commandExecutor.CommandExecuted += CommandExecutor_CommandExecuted; + commandExecutor.CommandManager = this; + + if (notify) + { + NotifyCommandReady(); + } } public void RemoveCommandExecutor(MtExpert commandExecutor) @@ -51,80 +48,88 @@ namespace MTApiService if (commandExecutor == null) return; + var notify = false; lock (_locker) { - if (mCommandExecutors.Contains(commandExecutor) == false) + if (_commandExecutors.Contains(commandExecutor) == false) return; - mCommandExecutors.Remove(commandExecutor); - - if (mCurrentExecutor == commandExecutor) + _commandExecutors.Remove(commandExecutor); + if (_commandTasks.Count > 0) { - mCurrentExecutor.IsCommandExecutor = false; - mCurrentExecutor = mCommandExecutors.Count > 0 ? mCommandExecutors[0] : null; - - if (mCommands.Count > 0) - { - mCurrentExecutor.NotifyCommandReady(); - } + notify = true; } } + + 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; lock (_locker) { - mCommands.Enqueue(command); - - mCurrentExecutor.NotifyCommandReady(); + _commandTasks.Enqueue(task); } + + NotifyCommandReady(); } - public MtCommand DequeueCommand() + public MtCommandTask DequeueCommandTask() { lock (_locker) { - return mCommands.Count > 0 ? mCommands.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(); - } - } + return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null; } } #endregion - #region Events - public event EventHandler CommandExecuted; + #region Private Methods + private void NotifyCommandReady() + { + var commandExecutors = new List(); + 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 #region Private Fields - private MtExpert mCurrentExecutor; - - private List mCommandExecutors = new List(); - private Queue mCommands = new Queue(); + private readonly List _commandExecutors = new List(); + private readonly Queue _commandTasks = new Queue(); private readonly object _locker = new object(); #endregion diff --git a/MTApiService/MtExpert.cs b/MTApiService/MtExpert.cs index dc03cb75..7ea328d8 100755 --- a/MTApiService/MtExpert.cs +++ b/MTApiService/MtExpert.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MTApiService { @@ -10,43 +7,46 @@ namespace MTApiService public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote); #region Properties - private MtQuote _Quote; + private MtQuote _quote; public MtQuote Quote { get { lock (_locker) { - return _Quote; + return _quote; } } set { lock(_locker) { - _Quote = value; + _quote = value; } - if (QuoteChanged != null) - { - QuoteChanged(this, value); - } + FireOnQuoteChanged(value); } } + public int Handle { get; private set; } - private volatile bool _IsEnable = true; + private bool _isEnable = true; public bool IsEnable { - get { return _IsEnable; } - private set { _IsEnable = value; } - } - - private volatile bool _IsCommandExecutor = true; - public bool IsCommandExecutor - { - get { return _IsCommandExecutor; } - set { _IsCommandExecutor = value; } + get + { + lock (_locker) + { + return _isEnable; + } + } + private set + { + lock (_locker) + { + _isEnable = value; + } + } } public ICommandManager CommandManager @@ -55,14 +55,14 @@ namespace MTApiService { lock (_locker) { - return mCommandManager; + return _commandManager; } } set { lock (_locker) { - mCommandManager = value; + _commandManager = value; } } } @@ -73,51 +73,43 @@ namespace MTApiService { Quote = quote; Handle = handle; - mMtHadler = mtHandler; + _mtHadler = mtHandler; } public void Deinit() { IsEnable = false; - - if (Deinited != null) - { - Deinited(this, EventArgs.Empty); - } + FireOnDeinited(); } public void SendResponse(MtResponse response) { - MtCommand command = mCommand; - mCommand = null; - - ICommandManager commandManager = CommandManager; - if (commandManager != null) - { - commandManager.OnCommandExecuted(this, command, response); - } + _commandTask.SetResult(response); + _commandTask = null; + FireOnCommandExecuted(); } public int GetCommandType() { - if (IsCommandExecutor) + var commandManager = CommandManager; + if (commandManager != null) { - ICommandManager commandManager = CommandManager; - if (mCommandManager != null) - { - mCommand = mCommandManager.DequeueCommand(); - } + _commandTask = commandManager.DequeueCommandTask(); } - return mCommand != null ? mCommand.CommandType : 0; + return _commandTask != null && _commandTask.Command != null ? _commandTask.Command.CommandType : 0; } public object GetCommandParameter(int index) { - if (mCommand != null && mCommand.Parameters != null - && index >= 0 && index < mCommand.Parameters.Count) + if (_commandTask != null) { - 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; @@ -131,13 +123,39 @@ namespace MTApiService } #endregion - #region Private Methods 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 @@ -145,12 +163,13 @@ namespace MTApiService #region Events public event EventHandler Deinited; public event MtQuoteHandler QuoteChanged; + public event EventHandler CommandExecuted; #endregion #region Private Fields - private readonly IMetaTraderHandler mMtHadler; - private MtCommand mCommand; - private ICommandManager mCommandManager; + private readonly IMetaTraderHandler _mtHadler; + private MtCommandTask _commandTask; + private ICommandManager _commandManager; private readonly object _locker = new object(); #endregion } diff --git a/MTApiService/MtServer.cs b/MTApiService/MtServer.cs index 21c3a80f..6bef6ea9 100755 --- a/MTApiService/MtServer.cs +++ b/MTApiService/MtServer.cs @@ -1,18 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading; using System.ServiceModel; using System.Net; using System.Diagnostics; using System.ServiceModel.Channels; -using System.Runtime.InteropServices; using System.Net.Sockets; namespace MTApiService { - class MtServer : IDisposable, IMtApiServer + internal class MtServer : IDisposable, IMtApiServer { #region Constants private const int WAIT_RESPONSE_TIME = 40000; // 40 sec @@ -23,12 +20,7 @@ namespace MTApiService public MtServer(int port) { Port = port; - mService = new MtService(this); - - mHosts = new List(); - - mExecutorManager = new MtCommandExecutorManager(); - mExecutorManager.CommandExecuted += mExecutorManager_CommandExecuted; + _service = new MtService(this); } #endregion @@ -39,21 +31,18 @@ namespace MTApiService #region Public Methods public void Start() { - bool hostsInitialized = InitHosts(Port); + var hostsInitialized = InitHosts(Port); if (hostsInitialized == false) - return; - - lock (mExpertsLocker) { - mExperts = new List(); + Debug.WriteLine("Start: InitHosts failed. "); } } private bool InitHosts(int port) { - lock (mHostLocker) + lock (_hosts) { - if (mHosts.Count > 0) + if (_hosts.Count > 0) return false; //init local pipe host @@ -61,7 +50,7 @@ namespace MTApiService ServiceHost localServiceHost = CreateServiceHost(localUrl, true); if (localServiceHost != null) { - mHosts.Add(localServiceHost); + _hosts.Add(localServiceHost); } //init network hosts @@ -79,7 +68,7 @@ namespace MTApiService ServiceHost serviceHost = CreateServiceHost(networkUrl, false); if (serviceHost != null) { - mHosts.Add(serviceHost); + _hosts.Add(serviceHost); } } } @@ -97,8 +86,8 @@ namespace MTApiService { try { - serviceHost = new ServiceHost(mService); - Binding binding = CreateConnectionBinding(local); + serviceHost = new ServiceHost(_service); + var binding = CreateConnectionBinding(local); serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress); serviceHost.Open(); @@ -116,17 +105,17 @@ namespace MTApiService { if (expert != null) { - expert.Deinited += new EventHandler(expert_Deinited); - expert.QuoteChanged += new MtExpert.MtQuoteHandler(expert_QuoteChanged); + expert.Deinited += expert_Deinited; + 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) { - EventWaitHandle responseWaiter = new AutoResetEvent(false); - - lock (mResponseLocker) - { - mResponseWaiters[command] = responseWaiter; - } - - mExecutorManager.EnqueueCommand(command); + var task = new MtCommandTask(command); + _executorManager.EnqueueCommandTask(task); //wait for execute command in MetaTrader - responseWaiter.WaitOne(WAIT_RESPONSE_TIME); - - lock (mResponseLocker) - { - if (mResponseWaiters.ContainsKey(command) == true) - { - mResponseWaiters.Remove(command); - } - - if (mResponses.ContainsKey(command) == true) - { - response = mResponses[command]; - mResponses.Remove(command); - } - } + response = task.WaitResult(WAIT_RESPONSE_TIME); } return response; @@ -172,9 +141,9 @@ namespace MTApiService public IEnumerable 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 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) { - mService.OnStopServer(); + _service.OnStopServer(); - stop(); + Stop(); } var stopTimer = sender as System.Timers.Timer; - stopTimer.Stop(); - stopTimer.Elapsed -= stopTimer_Elapsed; + if (stopTimer != null) + { + stopTimer.Stop(); + stopTimer.Elapsed -= stopTimer_Elapsed; + } } private string CreateConnectionAddress(string host, int port, bool local) @@ -265,65 +237,62 @@ namespace MTApiService 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; try { - foreach (var host in mHosts) + foreach (var host in _hosts) { host.Close(); } } catch (TimeoutException) { - foreach (var host in mHosts) + foreach (var host in _hosts) { host.Abort(); } } catch (Exception) { + // ignored } finally { - mHosts.Clear(); + _hosts.Clear(); } } - if (Stopped != null) - { - Stopped(this, EventArgs.Empty); - } + FireOnStopped(); } private void expert_Deinited(object sender, EventArgs e) { - MtExpert expert = (MtExpert)sender; - int expertsCount = 0; + if (sender == null) + return; - lock (mExpertsLocker) + var expert = (MtExpert)sender; + var expertsCount = 0; + + lock (_experts) { - mExperts.Remove(expert); - - expertsCount = mExperts.Count(); + _experts.Remove(expert); + expertsCount = _experts.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) { @@ -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) { - mService.QuoteUpdate(quote); + _service.QuoteUpdate(quote); + } + + private void FireOnStopped() + { + var handler = Stopped; + if (handler != null) + { + handler(this, EventArgs.Empty); + } } #endregion @@ -367,25 +326,16 @@ namespace MTApiService #region IDispose public void Dispose() { - stop(); + Stop(); } #endregion #region Fields - private readonly MtService mService; - private readonly List mHosts; - - private readonly MtCommandExecutorManager mExecutorManager; - private List mExperts; - - private readonly Dictionary mResponseWaiters = new Dictionary(); - private readonly Dictionary mResponses = new Dictionary(); - - private readonly object mResponseLocker = new object(); - private readonly object mHostLocker = new object(); - private readonly object mExpertsLocker = new object(); - private readonly object mCommandExecutorsLocker = new object(); + private readonly MtService _service; + private readonly List _hosts = new List(); + private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager(); + private readonly List _experts = new List(); #endregion } } diff --git a/mq4/Trend.zip b/mq4/Trend.zip deleted file mode 100755 index 12b150fb..00000000 Binary files a/mq4/Trend.zip and /dev/null differ