/// <summary>
        /// Determina l'avvio della procedura che permette di inviare il task specificato al servizio di elaborazione,
        /// di verificarne periodicamente il completamento e di eseguire alla fine il download dei relativi risultati
        /// eventualmente prodotti.
        /// </summary>
        /// <remarks>
        /// Prima di invocare questo metodo, è necessario utilizzare il metodo SetTaskData per poter impostare i dati
        /// relativi al task da elaborare.
        /// Inoltre, questo metodo non dovrebbe essere invocato sul thread della UI, in quanto la verifica periodica
        /// del completamento dell'elaborazione blocca tale thread per l'intervallo di polling specificato.
        /// </remarks>
        public void Start()
        {
            if (m_Proxy == null)
            {
                try
                {
                    RaiseTaskExecutionProgress(TaskRequestState.InitializingProxy, null);
                    m_Proxy = new ProcessingServiceClient(m_Binding, m_Endpoint);
                    m_Proxy.Open();
                    RaiseTaskExecutionProgress(TaskRequestState.ProxyInitialized, null);

                    RaiseTaskExecutionProgress(TaskRequestState.SendingRequest, null);
                    m_TaskRequestId = m_Proxy.SubmitData(m_TaskData);
                    RaiseTaskExecutionProgress(TaskRequestState.RequestSent, null);

                    bool completed = false;
                    while (!completed)
                    {
                        m_PollingWaitHandle.WaitOne(m_PollingInterval);
                        TaskState ts = m_Proxy.GetState(m_TaskRequestId);

                        switch (ts)
                        {
                        case TaskState.Completed:
                            RaiseTaskExecutionProgress(TaskRequestState.DownloadingResults, null);
                            m_TaskResults = m_Proxy.GetResults(m_TaskRequestId);
                            RaiseTaskExecutionProgress(TaskRequestState.ResultsDownloaded, null);
                            RaiseTaskExecutionCompleted(false, null, m_TaskResults);
                            completed = true;
                            break;

                        case TaskState.None:
                            completed = true;
                            break;

                        default:
                            completed = false;
                            break;
                        }
                    }

                    RaiseTaskExecutionProgress(TaskRequestState.DisposingProxy, null);
                    m_Proxy.Close();
                    RaiseTaskExecutionProgress(TaskRequestState.ProxyDisposed, null);
                }
                catch (Exception ex)
                {
                    HandleError(ex);
                }
            }
        }
        /// <summary>
        /// Determina l'avvio della procedura che permette di inviare il task specificato al servizio di elaborazione,
        /// di verificarne periodicamente il completamento e di eseguire alla fine il download dei relativi risultati
        /// eventualmente prodotti.
        /// </summary>
        /// <remarks>
        /// Prima di invocare questo metodo, è necessario utilizzare il metodo SetTaskData per poter impostare i dati
        /// relativi al task da elaborare.
        /// Inoltre, questo metodo non dovrebbe essere invocato sul thread della UI, in quanto la verifica periodica
        /// del completamento dell'elaborazione blocca tale thread per l'intervallo di polling specificato.
        /// </remarks>
        public void Start()
        {
            if (m_Proxy == null)
            {
                try
                {
                    RaiseTaskExecutionProgress(TaskExecutionState.InitializingProxy, null);
                    m_Proxy = new ProcessingServiceClient(m_Binding, m_Endpoint);
                    m_Proxy.Open();
                    RaiseTaskExecutionProgress(TaskExecutionState.ProxyInitialized, null);

                    RaiseTaskExecutionProgress(TaskExecutionState.SendingRequest, null);
                    m_TaskRequestId = m_Proxy.SubmitData(m_TaskData);
                    RaiseTaskExecutionProgress(TaskExecutionState.RequestSent, null);

                    bool completed = false;
                    while (!completed)
                    {
                        m_PollingWaitHandle.WaitOne(m_PollingInterval);
                        TaskState ts = m_Proxy.GetState(m_TaskRequestId);

                        switch (ts)
                        {
                            case TaskState.Completed:
                                RaiseTaskExecutionProgress(TaskExecutionState.DownloadingResults, null);
                                m_TaskResults = m_Proxy.GetResults(m_TaskRequestId);
                                RaiseTaskExecutionProgress(TaskExecutionState.ResultsDownloaded, null);
                                completed = true;
                                break;

                            case TaskState.None:
                                completed = true;
                                break;

                            default:
                                completed = false;
                                break;
                        }
                    }

                    RaiseTaskExecutionProgress(TaskExecutionState.DisposingProxy, null);
                    m_Proxy.Close();
                    RaiseTaskExecutionProgress(TaskExecutionState.ProxyDisposed, null);

                    RaiseTaskExecutionCompleted(false, null, m_TaskResults);
                }
                catch (Exception ex)
                {
                    HandleError(ex);
                }
            }
        }
        /// <summary>
        /// Interroga il servizio di elaborazione remota specificato al momento della creazione di questo oggetto
        /// al fine di ricevere le eventuali risorse di calcolo messe a disposizione da tale servizio e l'istante
        /// di ricezione della risposta da parte del servizio stesso. Se non si verifica nessun errore durante la
        /// comunicazione col servizio, questo metodo restituisce true; in caso contratio restituisce false.
        /// </summary>
        /// <param name="resources">L'elenco risorse eventualmente disponibili sul server di elaborazione.</param>
        /// <param name="detection">L'istante di più recente rilevazione del server di elaborazione.</param>
        /// <returns>true se non si verifica nessun errore durante la comunicazione; in caso contrario false.</returns>
        public bool TryGetResources(out IEnumerable<TaskPerformerInfo> resources, out DateTime detection)
        {
            lock (m_SyncLock)
            {
                if (m_MonitorClosed || m_BindingConfig == null || m_RemoteUri == null)
                {
                    resources = default(IEnumerable<TaskPerformerInfo>);
                    detection = default(DateTime);
                    return false;
                }

                try
                {
                    if (m_InternalProxy == null)
                    {
                        m_InternalProxy = new ProcessingServiceClient(m_BindingConfig, new EndpointAddress(m_RemoteUri));
                        m_InternalProxy.Open();
                    }

                    string[] resourcesList = m_InternalProxy.QueryForEnabledResources();
                    detection = DateTime.Now;

                    HashSet<TaskPerformerInfo> resourceSet = new HashSet<TaskPerformerInfo>();
                    foreach (var resourceItem in resourcesList)
                        resourceSet.Add(new TaskPerformerInfo(resourceItem));

                    resources = resourceSet;
                    return true;
                }
                catch
                {
                    if (m_InternalProxy != null)
                    {
                        if (m_InternalProxy.State == CommunicationState.Faulted)
                        {
                            m_InternalProxy.Abort();
                            m_InternalProxy = null;
                        }
                    }

                    resources = default(IEnumerable<TaskPerformerInfo>);
                    detection = default(DateTime);
                    return false;
                }
            }
        }