Exemple de port série comms code à l'aide d'API Asynchrone .net 4.5?

Quelqu'un peut-il m'indiquer un exemple qui utilise le .net 4.5 API Asynchrone (async, attendent, tâche<>, ReadAsync, etc) pour faire des communications en série?

J'ai essayé d'adapter un événement piloté de série de l'échantillon, et les ai toutes sortes d'horribles comportement - "port en cours d'utilisation par une autre application" des erreurs, VS2013 débogueur de lever des exceptions et des blocages qui habituellement nécessitent un redémarrage du PC pour récupérer à partir.

modifier

J'ai écrit mon propre exemple à partir de zéro. C'est un simple projet Winforms qui écrit dans la fenêtre de Sortie. Trois boutons sur la forme - Ouvrir le Port, à Proximité du Port, et de Lire les Données. Le ReadDataAsync les appels de méthode SerialPort.BaseStream.ReadAsync.

Comme de maintenant, il va lire des données à partir du port, mais je suis en cours d'exécution dans les problèmes de décision robuste.

Par exemple, si je débranchez le câble série, ouvrez le port, puis cliquez sur Lire les Données deux fois, je vais obtenir un Système.IO.IOException (que je sorte de s'attendre), mais mon application cesse de répondre.

Pire, quand j'essaie d'arrêter mon programme, VS2013 lance une "Arrêter le Débogage en cours de dialogue", qui ne se termine jamais, et je ne peux même pas tuer VS partir du Gestionnaire de Tâches. Avoir à redémarrer mon PC à chaque fois que cela se produit.

Pas bon.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private SerialPort _serialPort;
public Form1()
{
InitializeComponent();
}
private void openPortbutton_Click(object sender, EventArgs e)
{
try
{
if (_serialPort == null )
_serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
if (!_serialPort.IsOpen)
_serialPort.Open();
Console.Write("Open...");
}
catch(Exception ex)
{
ClosePort(); 
MessageBox.Show(ex.ToString());
}
}
private void closePortButton_Click(object sender, EventArgs e)
{
ClosePort();
}
private async void ReadDataButton_Click(object sender, EventArgs e)
{
try
{
await ReadDataAsync();
}
catch (Exception ex)
{
ClosePort();
MessageBox.Show(ex.ToString(), "ReadDataButton_Click");
}
}
private async Task ReadDataAsync()
{
byte[] buffer = new byte[4096];
Task<int> readStringTask = _serialPort.BaseStream.ReadAsync(buffer, 0, 100);
if (!readStringTask.IsCompleted)
Console.WriteLine("Waiting...");
int bytesRead = await readStringTask;
string data = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine(data);
}
private void ClosePort()
{
if (_serialPort == null) return;
if (_serialPort.IsOpen)
_serialPort.Close();
_serialPort.Dispose();
_serialPort = null;
Console.WriteLine("Close");
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
ClosePort();
}
}
}
SerialPort ne dispose pas de méthodes asynchrones car il est par nature asynchrone de la nature, il utilise des threads pour communitacions, il suffit donc de l'aide de ses méthodes et événements devrait être suffisant. Poster votre code de le revoir et de voir quel est le problème. Ajoutez également les erreurs.
Les autres, de SORTE postes implique que je peux utiliser des choses comme SerialPort.BaseStream.ReadAsync, etc. Je suis l'appel de cette méthode. Vous dites que cela ne fonctionnera pas?
Eh bien, si jamais de l'aide de l'underliying flux avec SerialPort, mais je soupçonne qu'il ne fonctionnera pas correctement (peut-être que je me trompe), je l'ai utilisé pendant des années le SerialPort et de l'utiliser avec l'Écriture et de la Lecture les fonctions et les DataReceived événement devrait être suffisant et déjà asynchrone.
L'exemple de projet que j'ai commencé avec utilise la DataRecieved événement. Je trouve l'INTERFACE utilisateur se bloque quand il y a beaucoup de données, donc je suis à la recherche d'une approche plus rigoureuse.
À l'aide de BaseStream.ReadAsync est exactement la bonne façon d'utiliser les ports série .NET, si vous êtes obligé d'utiliser la BCL classe SerialPort. (Encore mieux, c'est d'utiliser l'API Win32.) J'ai un blog à venir sur ce sujet, après mon superviseur approuvé.

OriginalL'auteur Tom Bushell | 2014-04-22