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.