Système.IO.Les Ports.SerialPort et le Multithreading

J'ai quelques SerialPort code qui a constamment besoin de lire des données à partir d'une interface série (par exemple COM1). Mais cela semble être beaucoup de temps CPU et si l'utilisateur déplace la fenêtre ou d'un lot de données est affiché à la fenêtre (tels que les octets reçus sur la ligne série) puis la communication se foiré.

Considérant le code suivant:

void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{

byte[] buffer = new byte[port.ReadBufferSize];

var count = 0;

try
{
    count = port.Read(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
    Console.Write(ex.ToString());
}

if (count == 0)
    return;

//Pass the data to the IDataCollector, if response != null an entire frame has been received


var response = collector.Collect(buffer.GetSubByteArray(0, count));

if (response != null)
{
    this.OnDataReceived(response);
}

Le code doit être collecté dans le flux de données est constante
et les données doivent être analysées (images/paquets).

    port = new SerialPort();

    //Port configuration code here...

    this.collector = dataCollector;

    //Event handlers
    port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
    port.Open();

Si il n'y a aucune interaction de l'utilisateur et rien n'a été ajouté à la fenêtre,
cela fonctionne bien mais dès qu'il y a une interaction de communication devient vraiment foiré.
Délais d'attente se produisent etc....

Par exemple, cela crée tout:

Dispatcher.BeginInvoke(new Action(() =>
{
  var builder = new StringBuilder();
  foreach (var r in data)
  {
      builder.AppendFormat("0x{0:X} ", r);
  }


  builder.Append("\n\n");

  txtHexDump.AppendText(builder.ToString());

  txtHexDump.ScrollToEnd();


}),System.Windows.Threading.DispatcherPriority.ContextIdle);
});

Mais même de simples appels à log4net causer des problèmes.

Existe-il des meilleures pratiques pour optimiser SerialPort communication
ou quelqu'un peut-il me dire ce que je fais mal...

Mise à jour:

Dans le cas ci-dessus n'a pas beaucoup de sens. J'ai fait un très simple (et stupide) petit exemple:

class Program
{
static void Main(string[] args)
{
var server = new BackgroundWorker();
server.DoWork += new DoWorkEventHandler(server_DoWork);
server.RunWorkerAsync();
var port = new SerialPort();
port.PortName = "COM2";
port.Open();
string input = "";
Console.WriteLine("Client on COM2: {0}", Thread.CurrentThread.ManagedThreadId);
while (input != "/quit")
{
input = Console.ReadLine();
if (input != "/quit")
{
var data = ASCIIEncoding.ASCII.GetBytes(input);
port.Write(data, 0, data.Length);
}
}
port.Close();
port.Dispose();
}
static void server_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Listening on COM1: {0}", Thread.CurrentThread.ManagedThreadId);
var port = new SerialPort();
port.PortName = "COM1";
port.Open();
port.ReceivedBytesThreshold = 15;
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
static void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var port = (SerialPort)sender;
int count = 0;
byte[] buffer = new byte[port.ReadBufferSize];
count = ((SerialPort)sender).Read(buffer, 0, buffer.Length);
string echo = ASCIIEncoding.ASCII.GetString(buffer,0,count);
Console.WriteLine("-->{1} {0}", echo, Thread.CurrentThread.ManagedThreadId);
}
}

Le résultat pourrait ressembler à ceci:

À l'écoute sur le port COM1: 6
Client sur le port COM2: 10
C'est un exemple de données que j'envoie
---> 6 Ceci est un exemple de données que j'envoie

Donc, la lecture de données à partir du port qui se passe sur le thread principal....

Cela peut-il être partie de ce qui est la cause de mes problèmes?

Où est la dernière section de code appelé? D'où vient le "data" variable venir?
Le code ci-dessus est appelée lorsque l'IDataCollector déclenche l'événement pour indiquer qu'il a recueilli une image complète de données. C'est dans le WPF, Windows. Mais même si vous ajoutez du journal.Warn(".....") énoncés dans le code de la IDataTransportServer ou IDataCollector implémentations de la SerialCommunication se fait défoncer... Les "données" est tout simplement ce que nous avons lu à partir de la ligne de série: mémoire tampon.GetSubByteArray(0, count)
Juste au sujet de n'importe quel code sera la cause de la communication Série à aller mal...

OriginalL'auteur TimothyP | 2009-06-10