Несколько асинхронных вызовов методов для метода в цикле - PullRequest
2 голосов
/ 12 марта 2010

Я провел целый день, пытаясь различными способами использовать AddOnPreRenderCompleteAsync и RegisterAsyncTask, но пока безуспешно.

Мне удалось сделать асинхронный вызов в БД с использованием «BeginExecuteReader» и «EndExecuteReader», но в этом нет смысла. Асинхронная обработка не должна быть вызовом БД, который в моем случае является быстрым, это должно происходить впоследствии, во время цикла while, при вызове внешнего веб-сервиса.

Я думаю, что упрощенный псевдокод объяснит лучше:
(Примечание: строка подключения использует 'MultipleActiveResultSets')

private void MyFunction()
{
    "Select ID, UserName from MyTable"
    // Open connection to DB
    ExecuteReader();
    if (DR.HasRows)
    {
        while (DR.Read())
        {
            // Call external web-service
            // and get current Temperature of each UserName - DR["UserName"].ToString()
            // Update my local DB 
            Update MyTable set Temperature = ValueFromWebService where UserName = 
                    DR["UserName"];

            CmdUpdate.ExecuteNonQuery();
        }

        // Close connection etc
    }
}

Быстрый доступ к БД. Получение возвращенного результата от внешнего веб-сервиса происходит медленно и, по крайней мере, должно обрабатываться асинхронно.

Если каждый вызов веб-службы занимает всего 1 секунду, при условии, что у меня всего 100 пользователей, для завершения обновления БД потребуется не менее 100 секунд, что, очевидно, не вариант.
Со временем должно быть тысячи пользователей (в настоящее время только 2).

В настоящее время все работает, просто очень синхронно :)
Мысли про себя:
Может быть, мой подход к этому неверен?
Может быть, весь процесс должен называться асинхронно?

Большое спасибо

Ответы [ 4 ]

1 голос
/ 12 марта 2010

Ты не думал о том, чтобы спрятать все это в свою собственную нить?

0 голосов
/ 17 марта 2010

Я бы сказал: создайте тему для каждого веб-запроса и сделайте что-то вроде этого:

дополнительные функции:

int privCompleteThreads = 0;
int OpenThreads = 0;
int CompleteThreads
{
  get{ return privCompleteThreads; }
  set{ privCompleteThreads = value; CheckDoneOperations(); }
}
void CheckDoneOperations
{
  if(CompleteThreads == OpenThreads)
  {
    //done!
  }
}

в основной программе:

foreach(time i need to open a request)
{
  OpenThreads = OpenThreads + 1;
  //Create thread here
}

внутри резьбовой функции:

//do your other stuff here

//do this when done the operation:
CompleteThreads = CompleteThreads + 1;

теперь я не уверен, насколько надежным будет этот подход, решать только вам. но обычный веб-запрос не должен занимать ни секунды, ваш браузер не занимает вторую загрузку этой страницы, не так ли? мой загружает его так быстро, как я могу нажать F5. Это просто открытие потока, вы можете попробовать открыть веб-запрос один раз и просто использовать один и тот же экземпляр снова и снова, и посмотреть, ускоряет ли это вообще

0 голосов
/ 17 марта 2010

Вы должны держать соединение с базой данных открытым как можно меньше времени. Поэтому не выполняйте никаких действий при переборе данных через DataReader. Большинство разработчиков приложений предпочитают размещать свой фактический код доступа к базе данных на отдельном уровне, и в таком случае вы бы возвращали DataTable или типизированную коллекцию вызывающему коду. Кроме того, если вы обновляете ту же таблицу, из которой читаете, это может привести к блокировке.

Сколько пользователей будут использовать этот метод одновременно и как часто его нужно обновлять? Вы уверены, что вам нужно сделать это из веб-приложения? Вы можете рассмотреть возможность использования синглтона для этого, и в этом случае выделение нескольких рабочих потоков совершенно уместно, даже если оно находится в веб-приложении. Еще одна вещь, которую следует учитывать, - это использование службы Windows, которая, на мой взгляд, более подходит для периодического обновления данных через веб-службу, которая даже не связана с сеансом текущего пользователя.

0 голосов
/ 12 марта 2010

Что на самом деле вас беспокоит?

Избегать долгой задачи, блокирующей ваше приложение? Если это так, вы можете использовать поток (см. BackgroundWorker)

Параллельно обрабатывать несколько обращений к веб-сервису, чтобы ускорить процесс размышления? Если это так, возможно, веб-сервис может быть вызван асинхронно с обратным вызовом. Вы также можете использовать ThreadPool или Tasks . Но вам придется дождаться завершения всех ваших вызовов или задач, прежде чем приступить к обновлению БД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...