Лучший способ ничего не делать, пока все не подключено в C # - PullRequest
5 голосов
/ 13 июня 2011

Я просматривал код для подключения к БД в одном из приложений, над которым я работаю, и увидел это

 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;

Цикл while беспокоит меня. Есть ли лучший способ ничего не делать, пока все не соединится?

EDIT:

Соединение получается следующим образом

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

Ответы [ 4 ]

6 голосов
/ 13 июня 2011

Хотя цикл работает и является допустимой стратегией ожидания какой-либо фоновой операции, другие ответы, похоже, упускают ключевой момент;Вы должны позволить фоновой операции сделать некоторую работу.Чередование циклов while не очень продуктивно, но Windows сочтет основной поток приложения, который, вероятно, выполняет ожидание, очень важным, и будет проходить цикл сотни или тысячи раз, прежде чем когда-либо будет выполняться фоновая операция.получает один такт процессорного времени.

Чтобы избежать этого, используйте оператор Thread.Yield (), чтобы сказать процессору прокрутить все остальные потоки, ожидающие процессорного времени, и вернуться после завершения.Это позволяет компьютеру выполнять некоторую работу, пока вы ожидаете фонового процесса, вместо того, чтобы монополизировать ЦП, чтобы он вращался по существу в пустом цикле.Это действительно просто;Вот пересмотренный ответ Джастина:

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(); //tells the kernel to give other threads some time
}

if (timeOut)
{
    Console.WriteLine("Connection Timeout");
    // TODO: Handle your time out here.
}
2 голосов
/ 13 июня 2011

РЕДАКТИРОВАТЬ : Обратите внимание, что это работает для DbConnection, а не IDbConnection

Вы всегда можете использовать событие StateChange класса DbConnection вместо цикла while.

Проверьте это

1 голос
/ 13 июня 2011

Учитывая, что это веб-приложение, лучше всего рассчитать время, прошедшее с того момента, как вы начали пытаться подключиться и выйти, если оно превышает период ожидания.Очевидно, бросить исключение или обработать ситуацию в этой точке.

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: Handle your time out here.
}
0 голосов
/ 21 ноября 2013

Подключите обработчик к событию StateChange. Когда государство открыто, делай то, что нужно.

            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
        {

        }
    }
...