none
[UWP] Windows 10 Apps SerialDevice.FromIdAsync() method Not working RRS feed

  • Question

  • Bonjour, je suis confronté au problème suivant en essayant de dialoguer avec une carte arduino (dialogue qui fonctionne avec l'ancienne class SerialPort mais qui malheureusement n'existe plus en UWP) : la méthode fromIdAsync() ne fonctionne pas à tous les coups. elle semble même faire un "Break();" dans la méthode qui appel cette fonction lorsqu'elle n'arrive pas à s'exécuter.

    public PortCom(string portName, uint baudRate = 250000, SerialParity parity = SerialParity.None, ushort dataBits = 8, SerialStopBitCount stopBits = SerialStopBitCount.OnePointFive)
    		{
    			ManualResetEvent mWait = new ManualResetEvent(false);
    			getHandlePortAsync(portName, mWait);
    			mWait.WaitOne(3000);
    			if (arduino == null)
    			{
    				throw new OperationCanceledException($"Error to connect { portName } device");
    			}
    			arduino.BaudRate = baudRate;
    			arduino.Parity = parity;
    			arduino.DataBits = dataBits;
    			arduino.StopBits = stopBits;
    			
    			Debugger.Break();
    		}
    
    		private async void getHandlePortAsync(string portName, ManualResetEvent mWait)
    		{
    			//VID_2341 & PID_0042
    			DeviceInformationCollection myDevices = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelector(portName));
    			//DeviceInformationCollection myDevices = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(2341, 0042));
    			if (myDevices != null)
    			{
    				if(myDevices.Count != 0)
    				{
    					try
    					{
    						arduino = await SerialDevice.FromIdAsync(myDevices[0].Id);
    					}
    					catch (Exception e)
    					{
    						Debugger.Break();
    					}
    				}
    			}
    			mWait.Set();
    			return;
    		}

    le manualResetEvent permet de constater que le fonction getHandlePortAsync() ne s'est pas terminée puisque le token du manualResetEvent n'est pas valide.

    Je n'obtiens jamais d’exception provenant du try-catch, et parfois (de manière aléatoire et très rare) la fonction me renvoie un SerialDevice correctement. Les autres résultat que j'obtiens est l'exception

    System.OperationCanceledException

    j'ai également essayer avec :

      <Capabilities>
        <DeviceCapability Name="serialcommunication">
          <Device Id="any">
            <Function Type="name:serialPort" />
          </Device>
        </DeviceCapability>
      </Capabilities>
    sans changement, le résultat reste aléatoire avec plus de 90% de throw exception.

    En espérant avoir une solution rapide, Merci !

    F Jarnoin


    • Modifié Flo_J jeudi 14 janvier 2016 22:04 renommage de l'exception reçue
    • Type modifié Emile Supiot vendredi 29 janvier 2016 13:34
    jeudi 14 janvier 2016 22:02

Réponses

  • RÉSOLUT

    Bonjour, mon problème venait bien du await :

    "async et await permettent à une méthode longue de retourner le trait immédiatement (ou en tout cas au plus vite), elle peut exécuter son code en créant un tâche (Task). Le mot clé await permet d’attendre la fin d’une telle tâche. Async permet de marquer une méthode qui fera usage de await. "

    il suffit de transformer les fonctions async en Task,

    solution :

    private void getHandlePort()
            {
                string aqs = SerialDevice.GetDeviceSelector("COM3");
                DeviceInformationCollection myDevices;
                //VID_2341 & PID_0042
                try
                {
                    Task<DeviceInformationCollection> devicesResult = DeviceInformation.FindAllAsync(aqs).AsTask();
                    myDevices = devicesResult.Result;
                }
                catch (Exception)
                {
                    throw;
                }
                if (myDevices != null)
                {
                    if (myDevices.Count != 0)
                    {
                        try
                        {
                            Task<SerialDevice> result = SerialDevice.FromIdAsync(myDevices[0].Id).AsTask();
                            arduino = result.Result;
                        }
                        catch (Exception e)
                        {
                            Debugger.Break();
                        }
                    }
                }
            }

    cette solution marche à tous les coups pour moi sauf si la méthode FindAllAsync est appelé avant getHandlePort. (Je suis tombé sur ce cas à force de tester et re-tester mon code, qui provoque le bloquage de la tâche devicesResult avec le statut "non-démarré").

    Je n'ai plus besoin du manualResetEvent non plus.



    • Modifié Flo_J mardi 26 janvier 2016 22:08 cancellationToken => manualResetEvent
    • Marqué comme réponse Emile Supiot vendredi 29 janvier 2016 13:34
    mardi 26 janvier 2016 22:06

Toutes les réponses

  • Bonjour, F Jarnoin,


    Avez-vous essayé de procéder à la manière suivante dans la Catch-Block : 
                    Debug.WriteLine(e.Message); 
                    await Task.Delay(1000); 
                    serialDevice = await SerialDevice.FromIdAsync(id); 
    (source: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/0c638b8e-482d-462a-97e6-4d8bc86d8767/uwp-windows-10-apps-windowsdevicesserialcommunicationserialdevice-class-not-working?forum=wpdevelop
    Je vous remercie par avance de votre retour.

    Cordialement,
    Teodora


    Votez! Appel à la contribution TechNet Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    lundi 18 janvier 2016 10:14
    Modérateur
  • Bonjour, merci de votre réponse.

    j'ai bien sur essayé ce qui est mentionné dans ce topic, à la seule différence c'est que ce n'est pas la fonction await SerialDevice.FromIdAsync(id);  qui me renvois un throw (je tomberais dans mon Break();), mais bien ma propre exception :

    throw new OperationCanceledException($"Error to connect { portName } device");

    c'est comme si la fonction getHandlePortAsync() était aborté en passant dans le await.

    Je ne pense pas qu'exécuter cette fonction peut mettre plus de 3s à s'exécuter, d'où mon WaitOne(3000). (Dans le doute j'ai quand même essayer de laisser cette fonction s’exécuter plus de 5 minutes mais sans rien donner)


    Cordialement,

    F Jarnoin

    lundi 18 janvier 2016 16:53
  • Bonjour, Flo_J,

    Je vous conseille d'utiliser la solution proposée par utilisateur Josiah_B.

    Merci  de nous tenir au courant.

    Cordialement,
    Teodora


    Votez! Appel à la contribution TechNet Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    mardi 19 janvier 2016 15:03
    Modérateur
  • Bonjour,

    Aucune différence, mon programme ne rentre pas dans le catch, du coup faire

                            await Task.Delay(1000);
                            arduino = await SerialDevice.FromIdAsync(myDevices[0].Id);

    ne m'avance pas plus.

    Cette instanciation essaye de se faire 20 fois (à l'aide d'un for) sans un résultat autre que null la plupart du temps. j'ai tout de même eu 2 instanciations réussie dans la soirée (sur plus de 20 essais).

    Je pense que je vais repasser sur une version plus stable et plus facile d'utilisation que UWP pour les connexions serial. Je serais quand même curieux de connaitre à la fois la solution de ce problème et à la fois la bonne méthodologie pour utiliser ce nouvel objet SerialDevice

    Cordialement,

    F Jarnoin

    mardi 19 janvier 2016 20:58
  • RÉSOLUT

    Bonjour, mon problème venait bien du await :

    "async et await permettent à une méthode longue de retourner le trait immédiatement (ou en tout cas au plus vite), elle peut exécuter son code en créant un tâche (Task). Le mot clé await permet d’attendre la fin d’une telle tâche. Async permet de marquer une méthode qui fera usage de await. "

    il suffit de transformer les fonctions async en Task,

    solution :

    private void getHandlePort()
            {
                string aqs = SerialDevice.GetDeviceSelector("COM3");
                DeviceInformationCollection myDevices;
                //VID_2341 & PID_0042
                try
                {
                    Task<DeviceInformationCollection> devicesResult = DeviceInformation.FindAllAsync(aqs).AsTask();
                    myDevices = devicesResult.Result;
                }
                catch (Exception)
                {
                    throw;
                }
                if (myDevices != null)
                {
                    if (myDevices.Count != 0)
                    {
                        try
                        {
                            Task<SerialDevice> result = SerialDevice.FromIdAsync(myDevices[0].Id).AsTask();
                            arduino = result.Result;
                        }
                        catch (Exception e)
                        {
                            Debugger.Break();
                        }
                    }
                }
            }

    cette solution marche à tous les coups pour moi sauf si la méthode FindAllAsync est appelé avant getHandlePort. (Je suis tombé sur ce cas à force de tester et re-tester mon code, qui provoque le bloquage de la tâche devicesResult avec le statut "non-démarré").

    Je n'ai plus besoin du manualResetEvent non plus.



    • Modifié Flo_J mardi 26 janvier 2016 22:08 cancellationToken => manualResetEvent
    • Marqué comme réponse Emile Supiot vendredi 29 janvier 2016 13:34
    mardi 26 janvier 2016 22:06
  • Bonjour, Flo_J,

    Je vous remercie d'avoir partagé cette solution avec la communauté du forum.

    Cordialement,
    Teodora


    Votez! Appel à la contribution TechNet Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    jeudi 28 janvier 2016 15:23
    Modérateur