/// <summary>
        /// Creates an instance of the memory editor form and invokes an action on the memory editor's thread.
        /// </summary>
        /// <param name="PID">The PID of the process to edit</param>
        /// <param name="address">The address to start editing at</param>
        /// <param name="length">The length to edit</param>
        /// <param name="action">The action to be invoked on the memory editor's thread</param>
        /// <returns>Memory editor form</returns>
        public static MemoryEditor GetMemoryEditor(int PID, IntPtr address, long length, MemoryEditorInvokeAction action)
        {
            MemoryEditor ed = null;
            string id = PID.ToString() + "-" + address.ToString() + "-" + length.ToString();

            if (MemoryEditors.ContainsKey(id))
            {
                ed = MemoryEditors[id];

                ed.BeginInvoke(action, ed);

                return ed;
            }

            if (MemoryEditorsThreaded)
            {
                Thread t = new Thread(() =>
                {
                    ed = new MemoryEditor(PID, address, length);

                    if (!ed.IsDisposed)
                        action(ed);
                    if (!ed.IsDisposed)
                        Application.Run(ed);

                    Program.MemoryEditorsThreads.Remove(id);
                }, Utils.SixteenthStackSize);

                t.SetApartmentState(ApartmentState.STA);
                t.Start();

                Program.MemoryEditorsThreads.Add(id, t);
            }
            else
            {
                ed = new MemoryEditor(PID, address, length);
                if (!ed.IsDisposed)
                    action(ed);
                if (!ed.IsDisposed)
                    ed.Show();
            }

            return ed;
        }