Solved! Go to Solution.
public MainWindow()
{
InitializeComponent();
this.Completed += (sender, result) =>
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
MessageBox.Show("Result: " + result.Token);
}), null);
};
LocalGeoprocessingService.GetServiceAsync(gpkLocation, GPServiceType.SubmitJob, localGpService =>
{
if (localGpService.Error != null)
return;
lgs = localGpService;
Thread thread = new Thread(new ParameterizedThreadStart(this.ExecuteGPTask));
thread.Start("Background Thread");
this.ExecuteGPTask("UI Thread");
});
}
public void ExecuteGPTask(object token)
{
//Set up parameters
List<GPParameter> parameters = new List<GPParameter>();
string input = "5+5";
GPString inputParam = new GPString("input", input);
parameters.Add(inputParam);
// Check local GP service is running and there are >=1 tasks
if (this.lgs.Status != LocalServiceStatus.Running || this.lgs.Tasks.Count == 0)
return;
// Assumes only one task in GP Package (GPK)
string taskUri = this.lgs.Tasks[0].Url;
// Create a new Geoprocessor task
Geoprocessor gpContour = new Geoprocessor(taskUri);
gpContour.Token = token.ToString();
// Create a timer to schedule CheckJobStatusAsync calls
System.Timers.Timer timer = null;
// Handler for StatusUpdated event (in response to CheckJobStatusAsync)
gpContour.StatusUpdated += (s, e) =>
{
Geoprocessor geoprocessingTask = s as Geoprocessor;
switch (e.JobInfo.JobStatus)
{
case esriJobStatus.esriJobSubmitted:
// Disable automatic status checking.
geoprocessingTask.CancelJobStatusUpdates(e.JobInfo.JobId);
break;
case esriJobStatus.esriJobSucceeded:
if (this.Completed != null)
{
this.Completed(this, new MyEventArgs() { Token = gpContour.Token });
if (timer != null)
{
timer.Stop();
timer.Dispose();
}
}
// Get the results.
// geoprocessingTask.GetResultDataAsync(e.JobInfo.JobId, "<parameter name>");
break;
case esriJobStatus.esriJobFailed:
case esriJobStatus.esriJobTimedOut:
MessageBox.Show("operation failed");
break;
}
};
JobInfo jobInfo = gpContour.SubmitJob(parameters);
timer = new System.Timers.Timer(3000);
timer.Elapsed += (s, e) =>
{
gpContour.CheckJobStatusAsync(jobInfo.JobId);
};
timer.Start();
}
using System;
using System.Threading;
using System.Windows.Threading;
using ESRI.ArcGIS.Client;
namespace UpdateGraphicsConsole
{
class Program
{
static string _url = "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Wildfire/FeatureServer/0";
// Make sure the main thread is an STA thread
[STAThread]
static void Main(string[] args)
{
// The SynchronizationContext of the main thread is null.
// Create and set a new DispatcherSynchronizationContext.
var syncCtx = new DispatcherSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(syncCtx);
// Get the current dispatcher to check thread access.
Dispatcher d = Dispatcher.CurrentDispatcher;
// Create a FeatureLayer
FeatureLayer fl1 = new FeatureLayer
{
Url = _url,
ID = "23",
Mode = FeatureLayer.QueryMode.Snapshot,
AutoSave = false,
};
// Report which thread the FeatureLayer was created on
Console.WriteLine("FeatureLayer created on Thread " + d.Thread.ManagedThreadId.ToString());
// Register a handler for the Initialized event
fl1.Initialized += (sender, eventArgs) =>
{
// Report which thread the event fired on (this was always a different thread until the DispatcherSynchronizationContext was set
Console.WriteLine("Initialized event handled on Thread " + Dispatcher.CurrentDispatcher.Thread.ManagedThreadId.ToString());
// Get the FeatureLayer
FeatureLayer fl2 = sender as FeatureLayer;
// Get the FeatureLayer dispatcher
Dispatcher d1 = fl2.Dispatcher;
// Report the thread we're invoking the Update call on (this was always the original thread)
Console.WriteLine("Invoking Update on Thread " + d1.Thread.ManagedThreadId.ToString());
// CheckAccess always returned false because this code was running on a different thread until the DispatcherSynchronizationContext was set
if (fl2.Dispatcher.CheckAccess())
{
fl2.Update();
}
else
d1.BeginInvoke(
DispatcherPriority.Normal,
new Action(delegate()
{
fl2.Update();
}));
};
// Register a handler for the UpdateCompleted event and call SaveEdits()
fl1.UpdateCompleted += (sender, e) =>
{
// Get the FeatureLayer
FeatureLayer fl3 = sender as FeatureLayer;
// Get the FeatureLayer Dispatcher
Dispatcher d2 = fl3.Dispatcher;
// Update the graphic attribute (or perform any other edits)
fl3.Graphics[0].Attributes["description"] = Guid.NewGuid().ToString();
// Write out the new value
Console.WriteLine(
"Updated Graphic ObjectID "
+ fl3.Graphics[0].Attributes["objectid"]
+ " with Description: "
+ fl3.Graphics[0].Attributes["description"]);
// Call CheckAccess to confirm whether we need to post back to the original thread
// Then call SaveEdits
if (fl3.Dispatcher.CheckAccess())
{
fl3.SaveEdits();
}
else
d2.BeginInvoke(
DispatcherPriority.Normal,
new Action(() => fl3.SaveEdits()));
};
// Register a handler for the EndSaveEdits event and write out the status
fl1.EndSaveEdits += (sender, e) =>
{
Console.WriteLine(e.Success ? "Success" : "Fail");
// Can check results online at query endpoint (by description value, objectid, etc)
// http://sampleserver6.arcgisonline.com/arcgis/rest/services/Wildfire/FeatureServer/0/query
};
// Register a handler for the InitializationFailed event
fl1.InitializationFailed += (sender, e) =>
{
// Report error
FeatureLayer fl4 = sender as FeatureLayer;
Console.WriteLine(fl4.InitializationFailure.Message);
};
// Register a handler for the UpdateFailed event
fl1.UpdateFailed += (sender, e) =>
{
// Report failure to update layer
Console.WriteLine(e.Error);
};
// Register a handler for the SaveEditsFailed event
fl1.SaveEditsFailed += (sender, e) =>
{
// Report failure
Console.WriteLine(e.Error);
};
Console.WriteLine("Calling Initialize on Thread " + d.Thread.ManagedThreadId.ToString());
// Call Initialize method (in a map/UI scenario this call would be handled by the Map).
fl1.Initialize();
// Need to call Dispatcher.Run
Dispatcher.Run();
}
}
}
Hi,
For your console app you should just need to create and set a new SynchronizationContext e.g.