/// <summary>
        /// Handles the click event of the Button and starts asynchronous geoprocessing.
        /// </summary>
        private void btnRunGP_Click(object sender, EventArgs e)
        {
            try
            {
                #region tidy up any previous gp runs

                //Clear the ListView control
                listView1.Items.Clear();

                //Remove any result layers present in the map
                IMapLayers mapLayers = axMapControl1.Map as IMapLayers;
                foreach (IFeatureLayer resultLayer in _resultsList)
                {
                    mapLayers.DeleteLayer(resultLayer);
                }

                axTOCControl1.Update();

                //Empty the results layer list
                _resultsList.Clear();

                //make sure that my GP tool queue is empty
                _myGPToolsToExecute.Clear();

                #endregion

                //Buffer the selected cities by the specified distance
                ESRI.ArcGIS.AnalysisTools.Buffer bufferTool = new ESRI.ArcGIS.AnalysisTools.Buffer();
                bufferTool.in_features = _layersDict["Cities"];
                bufferTool.buffer_distance_or_field = txtBufferDistance.Text + " Miles";
                bufferTool.out_feature_class        = "city_buffer.shp";

                //Clip the zip codes layer with the result of the buffer tool
                ESRI.ArcGIS.AnalysisTools.Clip clipTool = new ESRI.ArcGIS.AnalysisTools.Clip();
                clipTool.in_features       = _layersDict["ZipCodes"];
                clipTool.clip_features     = bufferTool.out_feature_class;
                clipTool.out_feature_class = "city_buffer_clip.shp";

                //To run multiple GP tools asynchronously, all tool inputs must exist before ExecuteAsync is called.
                //The output from the first buffer operation is used as an input to the second clip
                //operation. To deal with this restriction a Queue is created and all tools added to it. The first tool
                //is executed from this method, whereas the second is executed from the ToolExecuted event. This approach
                //is scalable - any additional geoprocessing tools added to this queue will also be executed in turn.
                _myGPToolsToExecute.Enqueue(bufferTool);
                _myGPToolsToExecute.Enqueue(clipTool);
                _gp.ExecuteAsync(_myGPToolsToExecute.Dequeue());
            }
            catch (Exception ex)
            {
                listView1.Items.Add(new ListViewItem(new string[2] {
                    "N/A", ex.Message
                }, "error"));
            }
        }