Hi,For your console app you should just need to create and set a new SynchronizationContext e.g.
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();
}
}
}
Cheers