Страницы

Поиск по вопросам

понедельник, 17 июня 2019 г.

Как убить Task который долго выполняется?

Есть запрос, который может выполняться до часа. Что бы не блокировать интерфейс пользователя, он проходит через Task. Если пользователю надоело ждать, надо этот запрос отменить. Как правильно это сделать, что бы соединение не висело целый час нагружая БД и пользователь их не создавал кучу? Может есть какие-то альтернативные варианты, кроме Task?
private void UpdateGrid(){ SomeRows rows; Task task = new Task(() => { rows = IDBConnectInstance.SelectRows(); }); task.ContinueWith(() => { dataGridView.DataSource = rows; }, TaskScheduler.FromCurrentSynchronizationContext()); }
UPD:
Каких либо дополнительных точек нету, сам IDBConnectInstance представляет собой интерфейс из сторонней библиотеки. То есть он входит в функцию библиотеки IDBConnectInstance.SelectRows и останавливается в ожидании завершения. Если бы была возможность обработать CancellationToken, вопрос бы не возник.
IDBConnect { SelectRows(); }
public class DBConnect: IDBConnect { public List SelectRows() { String query = "Очень долгий SELECT из БД"; List result = new List(); using(OracleConnection dbconn = new OracleConnection(ConnectionString)) { dbconn.Open();
OracleCommand command = new OracleCommand(query, dbconn); OracleDataReader reader = command.ExecuteReader(); while (reader.Read()) { SomeClass someClass = new someClass() { SomeField = reader[0], SomeField = reader[1], ... } result.Add(someClass); } reader.Close(); dbconn.Close(); } return result; } }
Пока есть только мысль вернуться на Thread и использовать устаревший Thread.Abort()


Ответ

Желательно дать пользователю возможность отмены, по команде.
private CancellationTokenSource _tokenSource; private bool _isWorked = false;
private void CancelUpdateGrid() { _tokenSource.Cancel(); }
private void UpdateGrid() { if (_isWorked) { return; }
_isWorked = true;
SomeRows rows;
// создаём CancellationTokenSource который отменит операцию _tokenSource = new CancellationTokenSource();
// В задачу передадим нужный нам токен. Task task = Task.Run(() => { var t = Thread.CurrentThread; using (cancellationSource.Token.Register(t.Abort)) { rows = IDBConnectInstance.SelectRows(); } }, _tokenSource.Token).ContinueWith(t => { dataGridView.DataSource = rows; _isWorked = false; }); }
Приведённый мною код упрощённый для понятия концепции с отменой.

Комментариев нет:

Отправить комментарий