/// <summary>
        /// Begins an asychronous traceroute to the specified destination.
        /// </summary>
        /// <param name="destination">The destination IP address.</param>
        /// <param name="callback">The callback method.</param>
        /// <param name="state">The user state.</param>
        /// <returns>The result of the asynchronous operation.</returns>
        public IAsyncResult Begin(IPAddress destination, AsyncCallback callback, object state)
        {
            lock (this.settings)
            {
                // Create a new traceroute state.
                TracerouteState asyncState = new TracerouteState(destination, this.settings.DataLength, callback, state);

                // Send a traceroute.
                this.Send(asyncState);

                // Return the asynchronous state.
                return asyncState;
            }
        }
        // Private methods.
        /// <summary>
        /// Send a traceroute message using the specified traceroute state.
        /// </summary>
        /// <param name="asyncState">The traceroute state.</param>
        private void Send(TracerouteState asyncState)
        {
            // Begin sending a traceroute message using the state.
            IAsyncResult result = asyncState.Begin((IAsyncResult asyncResult) =>
                {
                    // Finish sending a traceroute message using the state.
                    asyncState.End(asyncResult);

                    // A flag indicated whether the traceroute has completed.
                    bool completed = false;

                    lock (this.settings.Sync)
                    {
                        // Check whether the traceroute reached the destination.
                        completed = completed || (asyncState.LastReply != null ? asyncState.Destination.Equals(asyncState.LastReply.Address) &&
                            (this.settings.StopHopOnSuccess ? asyncState.TtlSuccess : asyncState.CurrentAttempt >= this.settings.MaximumAttempts) : false);
                        // Check whether the maximum number of hops was reached.
                        completed = completed || (asyncState.CurrentTtl > this.settings.MaximumHops);
                        // Check whether the maximum number of failed hops was reached.
                        completed = completed || (this.settings.StopTracerouteOnFail && (asyncState.LastFailedTtlCount + 1 >= this.settings.MaximumFailedHops) && (asyncState.CurrentAttempt >= this.settings.MaximumAttempts));
                        // Check whether the operation was canceled.
                        completed = completed || asyncState.CancellationToken.IsCancellationRequested;
                    }

                    // If the traceroute is completed, complete the asynchronous operation.
                    if (completed) asyncState.Complete();

                    // Call the callback method.
                    if (null != asyncState.Callback) asyncState.Callback(asyncState);

                    // If the operation is not completed.
                    if (!completed)
                    {
                        lock (this.settings.Sync)
                        {
                            // If the hop was successful, and the traceroute stops on success; or if the maximum number of attempts was reached.
                            if ((this.settings.StopHopOnSuccess && asyncState.TtlSuccess) || (asyncState.CurrentAttempt >= this.settings.MaximumAttempts))
                            {
                                // Increment the TTL.
                                asyncState.Next();
                            }
                        }
                        // Send a new message.
                        this.Send(asyncState);
                    }
                    else
                    {
                        // Dispose the asynchronous state.
                        asyncState.Dispose();
                    }
                });
        }