internal static JobResult FromJson(string json)
 {
     if (string.IsNullOrEmpty(json)) return null;
     var jObject = JObject.Parse(json);
     if (jObject == null || jObject.Count == 0) return null;
     var result = new JobResult();
     if (jObject["jobId"] != null && jObject["jobId"].Type == JTokenType.String)
         result.ID = jObject["jobId"].Value<string>();
     if (jObject["jobStatus"] != null && jObject["jobStatus"].Type == JTokenType.String)
         result.Status = (esriJobStatus)Enum.Parse(typeof(esriJobStatus), jObject["jobStatus"].Value<string>());
     return result;
 }
 private void GetResultLayer(JobResult jobResult, string taskUrl, string outputName, object userToken = null)
 {
     var client = new ArcGISWebClient();
     client.DownloadStringCompleted += (a, b) =>
     {
         var json = b.Result;
         var jObject = JObject.Parse(json);
         var fsJson = jObject["value"]["featureCollection"].ToString();
         OnAnalysisCompleted(new AnalysisEventArgs(FeatureSet.FromJson(fsJson), userToken));
     };
     var parameters = new Dictionary<string, string>();
     parameters["f"] = "json";
     parameters["token"] = Token;
     parameters["returnType"] = "data";
     client.DownloadStringAsync(new Uri(string.Format("{0}/jobs/{1}/results/{2}", taskUrl, jobResult.ID, outputName)), parameters);
 }
 private void CheckJobStatus(JobResult jobResult, string taskUrl, string outputName, object userToken = null)
 {
     var d = new DispatcherTimer();
     d.Interval = TimeSpan.FromMilliseconds(UpdateDelay);
     var gp = new Geoprocessor(taskUrl) { Token = Token, DisableClientCaching = true };
     gp.StatusUpdated += (s, e) =>
     {
         if (e.JobInfo.JobStatus == esriJobStatus.esriJobCancelled ||
             e.JobInfo.JobStatus == esriJobStatus.esriJobDeleted ||
             e.JobInfo.JobStatus == esriJobStatus.esriJobFailed ||
             e.JobInfo.JobStatus == esriJobStatus.esriJobSucceeded ||
             e.JobInfo.JobStatus == esriJobStatus.esriJobTimedOut)
         {
             d.Stop();
             if (e.JobInfo.JobStatus == esriJobStatus.esriJobSucceeded)
                 GetResultLayer(jobResult, taskUrl, outputName, userToken);
             else
                 OnAnalysisCompleted(new AnalysisEventArgs(new Exception(string.Format("Job has been {0}", e.JobInfo.JobStatus.ToString().ToLower().Replace("esrijob", string.Empty))), userToken));
         }
     };
     d.Tick += (s, e) =>
     {
         gp.CheckJobStatusAsync(jobResult.ID);
     };
     d.Start();
 }