.NET Core Async Method Call with TaskCompleted Callback

Here is a complete example showing how to write a call to an asynchronous Chilkat method in .NET Core. (Note: This is .NET Core, not .NET Framework.) This example uses the TaskCompleted callback to get notified when the task completes.
using System;
using System.Collections;

namespace ChilkatTest
{
    class Program
    {
        bool m_taskFinished = false;

        Hashtable m_chilkatTasks = new Hashtable();
        Hashtable m_chilkatSockets = new Hashtable();

        // This callback will occur within the background thread..
        public void Socket_HandleTaskIdCompleted(int taskId)
        {
            // Get the Chilkat task for this callback.
            Chilkat.Task task = (Chilkat.Task) m_chilkatTasks[taskId];
            if (task == null)
            {
                System.Diagnostics.Debug.WriteLine("Task not found.");
                return;
            }

            // Get the Chilkat socket.
            Chilkat.Socket socket = (Chilkat.Socket)m_chilkatSockets[taskId];
            if (socket == null)
            {
                System.Diagnostics.Debug.WriteLine("Socket not found.");
                return;
            }

            // Do whatever we want..

            // For this example, examine the contents of the socket.LastErrorText for both success and failure.
            System.Diagnostics.Debug.WriteLine(socket.LastErrorText);

            // Did the call socket connect successfully?
            if (task.GetResultBool() == true)
            {
                System.Diagnostics.Debug.WriteLine("The TLS connection was successful.");
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("The TLS connection failed.");
            }

            m_chilkatTasks.Remove(taskId);
            m_chilkatSockets.Remove(taskId);

            m_taskFinished = true;
        }


        // .NET Core async with TaskFinished callback.
        void TestSocketConnectAsync()
        {
            Chilkat.Socket socket = new Chilkat.Socket();

            // Setup the TaskCompleted callback.
            Chilkat.Socket.TaskIdCompleted taskIdCompleted = new Chilkat.Socket.TaskIdCompleted(Socket_HandleTaskIdCompleted);
            socket.setTaskIdCompletedCb(taskIdCompleted);

            Chilkat.Task task = socket.ConnectAsync("google.com", 443, true, 5000);
            if (socket.LastMethodSuccess == false)
            {
                System.Diagnostics.Debug.WriteLine(socket.LastErrorText);
                return;
            }

            // Save the task to our hashtable so we can access the Chilkat.Task object from within the TaskCompleted callback.
            m_chilkatTasks[task.TaskId] = task;

            // Also save the socket object for access within the TaskCompleted callback.
            m_chilkatSockets[task.TaskId] = socket;


            // Schedule the task for running on the thread pool.  This changes the task's state
            // from Inert to Live.
            bool success = task.Run();
            if (success != true)
            {
                System.Diagnostics.Debug.WriteLine(task.LastErrorText);
                return;
            }

        }

        void WaitUntilFinished()
        {
            while (!m_taskFinished)
            {
                System.Threading.Thread.Sleep(100);
            }
        }

        static bool UnlockChilkat()
        {
            Chilkat.Global glob = new Chilkat.Global();
            bool unlocked = glob.UnlockBundle("trial");
            if (!unlocked)
            {
                System.Diagnostics.Debug.WriteLine(glob.LastErrorText);
            }
            return unlocked;
        }

        static void Main(string[] args)
        {
            if (!UnlockChilkat()) return;

            Program prog = new Program();
            prog.TestSocketConnectAsync();

            // Wait for the async task to finish before exiting the program.
            prog.WaitUntilFinished();

            System.Diagnostics.Debug.WriteLine("Exiting..");
        }
    }
}