When use async method to open a form from another from it crashes C#

173 views Asked by At

Im using a KinectV2 and Project Praga to interpretate gestures and do things like control the media, domotic, etc.

when my async method is triggered by a gesture, needs to open another form, but when it happens this second form crashes:

using Microsoft.Gestures;
using Microsoft.Gestures.Endpoint;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace UIControl
{
    public partial class KinectProject : Form
    {

        private static GesturesServiceEndpoint _gesturesService;
        private static Gesture _One;

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Text = "Kinect Project Test";

        }

        public KinectProject()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e); InitializeGestures();
        }


        private async task InitializeGestures()
        {
            // One can optionally pass the hostname/IP address where the gestures service is hosted
            var gesturesServiceHostName = "localhost";
            await RegisterGestures(gesturesServiceHostName);
        }

        private static async Task RegisterGestures(string gesturesServiceHostName)
        {
            // Step 1: Connect to Microsoft Gestures service            
            _gesturesService = GesturesServiceEndpointFactory.Create(gesturesServiceHostName);
            await _gesturesService.ConnectAsync();

            // Step 2: Define bunch of custom Gestures, each detection of the gesture will emit some message into the console
            await RegisterOneGesture();

        }

        private static async Task RegisterOneGesture()
        {
            // Start with defining the first pose, ...
            var Iddle = new HandPose("iddle", new FingerPose(new AllFingersContext(), FingerFlexion.OpenStretched),
                                              new PalmPose(new AnyHandContext(), PoseDirection.Backward));

            var hold = new HandPose("Hold", new FingerPose(Finger.Index, FingerFlexion.Open, PoseDirection.Up),
                                            new FingerPose(new[] { Finger.Thumb, Finger.Middle, Finger.Ring, Finger.Pinky }, FingerFlexion.Folded),
                                            new PalmPose(new AnyHandContext(), PoseDirection.Backward));

            // ... finally define the gesture using the hand pose objects defined above forming a simple state machine: hold -> rotate
            _One = new Gesture("One", Iddle, hold);
            _One.Triggered += (s, e) => Executor(s);
            //_One.Triggered += (s, e) => OnGestureDetected(s, e, ConsoleColor.DarkRed);

            // Step 3: Register the gesture             
            // Registering the like gesture _globally_ (i.e. isGlobal:true), by global registration we mean this gesture will be 
            // detected even it was initiated not by this application or if the this application isn't in focus
            await _gesturesService.RegisterGesture(_One, isGlobal: true);
        }

        private static void OnGestureDetected(object sender, GestureSegmentTriggeredEventArgs args, ConsoleColor foregroundColor)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write("Gesture detected! : ");
            Console.ForegroundColor = foregroundColor;
            Console.WriteLine(args.GestureSegment.Name);

            Console.ResetColor();

        }
        
        static void Executor(object sender, GestureSegmentTriggeredEventArgs args, ConsoleColor foregroundColor)
        {
            MusicForm V1 = new MusicForm();
            V1.Show();
        }
    }
}

I recently add the override method but is the same, when MusicForm Opens it crashes, but if i use a button instead the MusicForm opens correctly

[Edit] i add this to Executor and fix OnLoad()

protected override async void OnLoad(EventArgs e)
    {
         base.OnLoad(e);
         await InitializeGestures();
    }


private void Executor(object sender)
    {
          int managedThreadId = Thread.CurrentThread.ManagedThreadId;
        MessageBox.Show("ManagedThreadId = " + managedThreadId);

        if (this.Handle == IntPtr.Zero)
        {
            // If the handle is not yet created, create it
            CreateHandle();
        }
        this.BeginInvoke((MethodInvoker)(delegate
        {
            MusicForm V1 = new MusicForm();
            V1.Show();
        }));

and ManagedThreadId returned ManagedThreadId = 6

1

There are 1 answers

6
filtrow On

You need to use the UI thread for these kind of operations. You can use invoke or begininvoke. Try to change your executor in

    this.Invoke(() =>
    {
        MusicForm V1 = new MusicForm();
        V1.Show();
    });