6 Stimmen

Beste Möglichkeit, nichts zu tun, bis Dinge in C# verbunden sind

Ich habe den Code zur Verbindung mit der Datenbank in einer der Anwendungen überprüft, an der ich arbeite, und das gesehen

 if (_dbConnection == null)
     _dbConnection = GetConnection();

 while (_dbConnection.State == ConnectionState.Connecting)
 {
     //Do Nothing until things are connected.
 }

 if (_dbConnection.State != ConnectionState.Open)
     _dbConnection.Open();

 var command = GetCommand(commandType);
 command.Connection = _dbConnection;
 return command;

Die while-Schleife macht mir Sorgen. Gibt es einen besseren Weg, um nichts zu tun, bis die Verbindung hergestellt ist?

BEARBEITEN:

Die Verbindung wird wie folgt hergestellt

private static IDbConnection GetConnection()
{
     return new SqlConnection(ConfigurationManager.ConnectionStrings["CoonectionStringName"].ConnectionString);
}

2 Stimmen

Welche Art von Verbindung? System.Data.SqlClient.SqlConnection?

1 Stimmen

Ich würde auch ein Timeout setzen sowie im while-Loop eine Verzögerungs-/Warte-Anweisung einfügen, damit keine CPU-Zeit verschwendet wird.

0 Stimmen

Die Klasse der Verbindung ist System.Data.IDbConnection

6voto

KeithS Punkte 67713

Obwohl die Schleife funktioniert und eine gültige Strategie zum Warten auf eine Hintergrundoperation ist, scheinen andere Antworten einen wichtigen Punkt zu verpassen; Sie müssen die Hintergrundoperation einige Arbeit erledigen lassen. Durch das Durcharbeiten einer Schleife ist nicht sehr produktiv, aber Windows wird den Hauptthread der App, der wahrscheinlich auf das Warten wartet, als sehr wichtig betrachten und Hunderte oder Tausende Male durch die Schleife laufen lassen, bevor die Hintergrundoperation jemals eine einzige CPU-Taktung erhält.

Um dies zu vermeiden, verwenden Sie die Thread.Yield() Anweisung, um dem Prozessor mitzuteilen, dass er durch alle anderen Threads gehen soll, die auf CPU-Zeit warten, und zurückzukommen, wenn sie fertig sind. Dadurch kann der Computer einige Arbeiten erledigen, während Sie auf den Hintergrundprozess warten, anstatt die CPU zu monopolisieren, um durch eine im Grunde leere Schleife zu laufen. Es ist wirklich einfach; hier ist Justins Antwort überarbeitet:

var startTime = DateTime.Now;
var endTime = DateTime.Now.AddSeconds(5);
var timeOut = false;

while (_dbConnection.State == ConnectionState.Connecting)
{
    if (DateTime.Now.CompareTo(endTime) >= 0)
    {
        timeOut = true;
        break;
    }
    Thread.Yield(); //sagt dem Kernel, anderen Threads etwas Zeit zu geben
}

if (timeOut)
{
    Console.WriteLine("Verbindungszeitüberschreitung");
    // TODO: Behandeln Sie hier Ihre Zeitüberschreitung.
}

2voto

Chandu Punkte 79046

BEARBEITEN: Bitte beachten Sie, dass dies für DbConnection funktioniert und nicht für IDbConnection

Sie können immer das StateChange-Ereignis der DbConnection-Klasse anstelle der While-Schleife verwenden.

Überprüfen Sie dies

0 Stimmen

Nur mal so in Gedanken. Was passiert, wenn die Verbindung nie zustande kommt? Wird das Ereignis dann nie ausgelöst werden?

0 Stimmen

@tou: Das sollte durch die Behandlung der Verbindungsabbruch-Ausnahme separat angegangen werden...

0 Stimmen

Würde das vollständig funktionieren? Was wäre wenn die gleiche Verbindung zurückgegeben würde? Du würdest Handler ansammeln.

1voto

Devin Burke Punkte 13442

Da es sich um eine Webanwendung handelt, ist es am besten, die Dauer der vergangenen Zeit seit dem Versuch der Verbindung zu berechnen und abzubrechen, wenn sie ein Zeitlimit überschreitet. Offensichtlich sollte an dieser Stelle eine Ausnahme ausgelöst oder die Situation behandelt werden.

var startTime = DateTime.Now;
var endTime = DateTime.Now.AddSeconds(5);
var timeOut = false;

while (_dbConnection.State == ConnectionState.Connecting)
{
    if (DateTime.Now.Compare(endTime) >= 0
    {
        timeOut = true;
        break;
    }
}

if (timeOut)
{
    // TODO: Behandeln Sie hier Ihre Zeitüberschreitung.
}

0 Stimmen

In diesem Szenario läuft die while-Schleife immer noch und beansprucht eine große Menge an Prozessorzeit.

0voto

Rubarb Punkte 55

Haken Sie einen Handler am StateChange-Ereignis an. Wenn der Status Open ist, machen Sie, was erforderlich ist.

m_SqlConnection = new SqlConnection(ConnectionStringBuilder.ConnectionString);
m_SqlConnection.StateChange += new System.Data.StateChangeEventHandler(m_SqlConnection_StateChange);
m_SqlConnection.Open();

void m_SqlConnection_StateChange(object sender, System.Data.StateChangeEventArgs e)
{
    try
    {
        if (m_SqlConnection.State == ConnectionState.Open)
        {
            // do stuff
        }
        if (m_SqlConnection.State == ConnectionState.Broken)
        {
            Close();
        }
        if (m_SqlConnection.State == ConnectionState.Closed)
        {
            Open();
        }
    }
    catch
    {

    }
}

0 Stimmen

I würde nicht empfehlen, dies zu tun, da jeder Zustandswechsel auf einem anderen Thread läuft und dies zu Inkonsistenzen führen kann, wenn die Verbindung von einem anderen Thread verwendet wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X