webentwicklung-frage-antwort-db.com.de

warum wird der Zugriff auf COM-Port nicht zugelassen?

der Code:

static void Main(string[] args)
{
    Console.WriteLine("Memory mapped file reader started");

    using (var file = MemoryMappedFile.OpenExisting("AIDA64_SensorValues"))
    {
        using (var readerz = file.CreateViewAccessor(0, 0))
        {
            var bytes = new byte[567];
            var encoding = Encoding.ASCII;
            readerz.ReadArray<byte>(0, bytes, 0, bytes.Length);

            File.WriteAllText("C:\\myFile.txt", encoding.GetString(bytes));

            var readerSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };
            using (var reader = XmlReader.Create("C:\\myFile.txt", readerSettings))
            {
                while (reader.Read())
                {
                    using (var fragmentReader = reader.ReadSubtree())
                    {
                        if (fragmentReader.Read())
                        {

                            reader.ReadToFollowing("value");
                            SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
                            port.Open();
                            port.Write(reader.ReadElementContentAsString() + ",");
                        }
                    }
                }
            }    
        }
    }

    Console.WriteLine("Press any key to exit ...");
    Console.ReadLine();
}

es liest den gemeinsam genutzten Speicher, schreibt diesen gemeinsam genutzten Speicher in eine Datei, dann wird dieselbe Datei mit dem XML-Leseprogramm geöffnet und die XML-Datei wird geteilt, da sie mehrere Wurzeln hat. Dann wird der Wert eines Knotens in jeder neuen aufgeteilten XML-Datei abgerufen und über die serielle Schnittstelle gesendet. Es funktioniert für die erste aufgeteilte XML-Datei, und der Knoten wird über die Seriennummer gesendet. Dann wird der Zugriff auf die COM-Port-Nachricht beim Versuch, den zweiten Knoten in die Seriennummer zu schreiben, verweigert.

ich habe eine andere App, die ich mit dem gleichen Seriencode erstellt habe, und sie funktioniert gut (ich habe sie nur müde gemacht und dann geschlossen.) ... also ist es seltsam.

11
Csharpz

Sie können eine serielle Schnittstelle nur einmal öffnen. Ihr Code hat jedoch den Aufruf von Open () in der while-Schleife. Das funktioniert nur beim ersten Durchgang durch die Schleife, beim zweiten Durchgang kaboom. Die Lösung von @ cdhowie funktioniert auch nicht. SerialPort hat eine Eigenart (auch bekannt als Fehler), vor der die Dokumentation warnt. Nach dem Aufruf von Dispose () oder Close () muss ein Worker-Thread beendet werden. Die Zeit ist unbestimmt und unvorhersehbar.

Die eigentliche Lösung ist einfach: Bewegen Sie den Open () - Aufruf vor der while-Schleife.

25
Hans Passant

Neben Hans 'Antwort:

Ich hatte das gleiche Problem und spielte ein bisschen herum mit ein paar Ruhezeiten zwischen dem Öffnen und Schließen der seriellen Schnittstelle. In meinem Fall waren 250 ms ausreichend. Vielleicht hilft das jemandem da draußen.

BEARBEITEN:

Ich habe meine Lösung optimiert und das ist, worauf ich gekommen bin:

int maxRetries = 20;
const int sleepTimeInMs = 50;
string loggingMessage = string.Empty;

while (maxRetries > 0)
{
    try
    {
        loggingMessage = "Opening serial port '" + mSerialPort.PortName + "'...";
        mSerialPort.Open();
        loggingMessage += "Succeeded.";
        IOLogger.LogInfo(loggingMessage);
    }
    catch (UnauthorizedAccessException unauthorizedAccessException)
    {
        maxRetries--;
        loggingMessage += "Failed (UnauthorizedAccessException): ";
        IOLogger.LogError(string.Format(loggingMessage + unauthorizedAccessException.Message + " -> Retrying in about {0} milliseconds...", sleepTimeInMs));
        Thread.Sleep(sleepTimeInMs);
    }
    catch (Exception exception)
    {
        loggingMessage += "Failed: ";
        IOLogger.LogError(loggingMessage + exception.Message);
    }
}

Sie können mit der sleepTimeInMs und/oder der maxRetries herumspielen. Ich habe diese Werte gewählt, weil sie in jedem erforderlichen Anwendungsfall ausreichend waren.

3
M. Hartner

Sie müssen den Port schließen und entsorgen, wenn er geöffnet ist, da er bei der letzten Verbindung nicht entsorgt wurde.

0

Hans 'Antwort tritt an diese Stelle; Ich lasse es nur zu Kontext- und Informationszwecken.


Sie müssen den Port schließen, wenn Sie damit fertig sind. Der Garbage Collector erfasst das erste SerialPort-Objekt nicht, bevor Sie versuchen, einen anderen Handle zu öffnen. Ändern Sie diesen Code:

SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
port.Open();
port.Write(reader.ReadElementContentAsString() + ",");

Zu:

using (SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One))) 
{
    port.Open();
    port.Write(reader.ReadElementContentAsString() + ",");
}
0
cdhowie

Die Lösung, die für mich funktioniert hat, lautet wie folgt: 1: Verwenden Sie try catch block und geben Sie den gesamten Code für das Öffnen und Schließen des Ports ein.

2: Verwenden Sie die IsOpen () - Funktion, um zu überprüfen, ob der Port bereits geöffnet ist oder nicht.

3: Wenn eine Ausnahme (Zugriff verweigert) auftritt, schreiben Sie den Port.Close () - Code in Ihren catch-Block, um diesen Port freizugeben.

4: Machen Sie das Objekt von der seriellen Schnittstelle, bevor Sie versuchen, den catch-Block universell zu machen.

5: Der Open () -Aufruf sollte sich nicht in der Schleife befinden. Sie sollten den Port nur einmal öffnen und nach der Schleife schließen.

Wenn Sie alle diese Schritte ausführen, wird dieses Problem nie wieder auftreten.

Ein Beispielcode ist unten angegeben:

GsmCommMain comm = new GsmCommMain(COMPort.ToString(), 9600, 500);

try{ for (int i = 0; i < dtObj.Rows.Count; i++)
                                    {
                                        if (dtObj.Rows[i]["smsNumber"] != null)
                                        {
                                            if (dtObj.Rows[i]["smsNumber"].ToString() != "")
                                            {
                                                if (dtObj.Rows[i]["status"].ToString() != "Sent")
                                                {
                                                    Thread.Sleep(Convert.ToInt32("50000"));
                                                    string txtMessage = dtObj.Rows[i]["sms"].ToString();
                                                    string txtDestinationNumbers = dtObj.Rows[i]["smsNumber"].ToString();
                                                    bool unicode = true;
                                                    SmsSubmitPdu[] pdu = SmartMessageFactory.CreateConcatTextMessage(txtMessage, unicode, txtDestinationNumbers);
                                                    comm.SendMessages(pdu);
                                                    obj_bal_ForAll.bal_forAll_Delete("tbl_SMS", "smsId", dtObj.Rows[i]["smsId"].ToString());
                                                }
                                            }
                                        }
                                    }
                                    if (comm.IsOpen())
                                    {
                                        comm.Close();
                                    }  
                                    }catch(Exception ex){if (comm.IsOpen()){comm.Close();}}
0
Muhammad Abbas