2015-03-01 1 views
1

Ниже приведен код, который я использую. Предназначен для асинхронного вызова функции времени.Асинхронная функция, работающая как синхронный вызов

async Task<DataSet> GetDataAsync() 
    { 
     System.Threading.Thread.Sleep(5000); 
     SqlDataAdapter adpator = new SqlDataAdapter("Select * from table1;select * from table2;select * from table3;select * from table4" 
      , @"Data Source=ANKIT\SQLEXPRESS;Initial Catalog=IM_DB;Integrated Security=True"); 
     DataSet ds = new DataSet(); 
     adpator.Fill(ds); 
     return ds; 
    } 

    protected async void btnFillData_Click(object sender, EventArgs e) 
    { 
     lblStatus.Text = "Going to run a blocking thread...."; 
     Task<DataSet> dsAsync = GetDataAsync(); 
     lblStatus.Text = "Going to await the same......"; 
     DataSet ds = await dsAsync; 
     lblStatus.Text = "released from await"; 
     gvIngredient.DataSource = ds.Tables[0]; 
     gvIngredient.DataBind(); 
    } 

Функция GetDataAsync работает как синхронный вызов. Я хочу, чтобы он был асинхронным, так как он имеет вызов базы данных для извлечения тысяч записей, требующих много времени.

Есть что-то, что я пропустил в async-модели на asp.net.

+0

Какая ошибка вы получаете? – Dnyanesh

+0

Чтобы заставить 'GetDataAsync' работать asynch, ваши вызовы на db' должны быть asynch', в противном случае вызовы блокируют –

+0

https://msdn.microsoft.com/en-us/library/hh211418(v=vs. 110) .aspx –

ответ

2

Первая проблема:

Модификатор async не делает ваш метод асинхронно, он просто дает вам возможность использовать await ключевое слово внутри. Таким образом, функция GetDataAsync не является асинхронной - она ​​использует тот же поток, который был вызван. Для того, чтобы сделать эту функцию асинхронно вы должны использовать Task класс и метод StartNew так:

Task<DataSet> GetDataAsync() 
{ 
    Function<DataSet> func =() => 
    { 
     System.Threading.Thread.Sleep(5000); 
     SqlDataAdapter adpator = new SqlDataAdapter("Select * from table1;select * from table2;select * from table3;select * from table4" 
       , @"Data Source=ANKIT\SQLEXPRESS;Initial Catalog=IM_DB;Integrated Security=True"); 
     DataSet ds = new DataSet(); 
     adpator.Fill(ds); 
     return ds; 
    }; 

    return Task.Factory.StartNew(func); 
} 

this Check действительно полезная статья вверх, чтобы понять как async\await работы.

Второе:

Ваш код сохраняет SqlDataAdapter в памяти после каждого вызова GetDataAsync. Это приводит к утечке памяти. Вы бы лучше использовать using заявление:

DataSet ds = new DataSet(); 
using(var adapter = new SqlDataAdapter(query, connectionString)) 
    adapter.Fill(ds); 

Надеется, что это помогает.

0

Функция GetDataAsync работает как синхронный вызов.

Да. На самом деле, есть предупреждение компилятора, которое сообщит вам, что GetDataAsync будет работать синхронно.

Это можно сделать асинхронным, но не используя подход DataSet.Fill. Это очень старый способ делать вещи и не обновлялся, чтобы использовать новые асинхронные API. Вы должны использовать что-то вроде Entity Framework 6 или асинхронных DbCommands.

Но прежде чем отправиться по этому пути ...

protected async void btnFillData_Click(object sender, EventArgs e) 
{ 
    lblStatus.Text = "Going to run a blocking thread...."; 
    Task<DataSet> dsAsync = GetDataAsync(); 
    lblStatus.Text = "Going to await the same......"; 
    DataSet ds = await dsAsync; 
    lblStatus.Text = "released from await"; 
    gvIngredient.DataSource = ds.Tables[0]; 
    gvIngredient.DataBind(); 
} 

Этот код показывает непонимание того, как работает ASP.NET. Когда кнопка нажата, на сервер ASP.NET отправляется один HTTP-запрос, и сервер может отправлять только один HTTP-ответ. Этот ответ отправляется только по адресу end метода события click. Таким образом, установка lblStatus.Text несколько раз не будет иметь никакого эффекта - только последнее обновление будет видно пользователю.

Иными словами, await на ASP.NET дает только время выполнения ASP.NET; он не уступает клиенту (браузеру). Ответ HTTP не отправляется до завершения всех await.

Итак, что вы на самом деле запрашиваемое как начать затянувшуюся работу в ASP.NET и затем обновление клиента позже с прогрессом или информацией завершения. Для этого вам понадобятся разные технологии, такие как SignalR, AJAX или UpdatePanel.

Смежные вопросы