У меня довольно простое приложение WPF, которое использует Entity Framework. На главной странице приложения есть список записей, которые я получаю из базы данных при запуске.Как мне реагировать на приложение во время операций Entity Framework?
Каждая запись имеет изображение, поэтому операция может быть немного медленной, когда беспроводной сигнал плохой. Я хотел бы, чтобы это (и многие из моих операций с SQL) выполнялось в фоновом режиме, если это было возможно. У меня есть настройка async/await, и сначала она работает точно так, как мне хотелось, но теперь я вижу, что мое приложение становится невосприимчивым при доступе к БД.
В конце концов я думаю, что собираюсь загрузить текст в одном запросе и изображениях в другую фоновую операцию и загрузить их по мере их поступления. Таким образом, я сразу получаю важные вещи, и фотографии могут появиться в фоновом режиме, но, как все происходит, все еще похоже, что он закроется, если я это сделаю.
Кроме того, я пытаюсь реализовать что-то для решения проблем с подключением (в случае, если wifi отключается на мгновение), так что приложение уведомляет пользователя о проблеме подключения, автоматически повторяет несколько раз и т. Д. I поместите попытку catch для SQL-исключения, которая, похоже, работает на меня, но все приложение блокируется примерно на минуту, пока пытается подключиться к БД.
Я попытался проверить мой асинхронный/ожидающий, используя await Task.Delay()
, и все очень отзывчивое, как ожидалось, в ожидании задержки, но все блокируется, ожидая .ToListAsync()
. Это нормально и ожидается? Мое понимание async/await довольно ограничено.
Мой код в некотором роде беспорядочен (я новичок), но он делает то, что мне нужно для этого, по большей части. Я понимаю, что, вероятно, есть много улучшений, которые я могу сделать, и лучшие способы сделать что-то, но один шаг за один раз здесь. Моя главная цель прямо сейчас заключается в том, чтобы не допустить, чтобы приложение зависало во время доступа к исключениям в базе данных и чтобы пользователь не уведомлял о том, что делает приложение (поиск, попытка доступа к db, невозможность достичь БД и повторная попытка и т. Д.), А не замораживание , и это то, что они собираются думать, когда они видят, что он не отвечает за минуту.
Некоторые из моего кода:
В моей основной модели представления
DataHelper data = new DataHelper();
private async void GetQualityRegisterQueueAsync()
{
try
{
var task = data.GetQualityRegisterAsync();
IsSearching = true;
await task;
IsSearching = false;
QualityRegisterItems = new ObservableCollection<QualityRegisterQueue>(task.Result);
OrderQualityRegisterItems();
}
catch (M1Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine("QualityRegisterLogViewModel.GetQualityRegisterQueue() Operation Failed");
}
}
Мои данные Helper Класс
public class DataHelper
{
private bool debugging = false;
private const int MAX_RETRY = 2;
private const double LONG_WAIT_SECONDS = 5;
private const double SHORT_WAIT_SECONDS = 0.5;
private static readonly TimeSpan longWait = TimeSpan.FromSeconds(LONG_WAIT_SECONDS);
private static readonly TimeSpan shortWait = TimeSpan.FromSeconds(SHORT_WAIT_SECONDS);
private enum RetryableSqlErrors
{
ServerNotFound = -1,
Timeout = -2,
NoLock = 1204,
Deadlock = 1205,
}
public async Task<List<QualityRegisterQueue>> GetQualityRegisterAsync()
{
if(debugging) await Task.Delay(5000);
var retryCount = 0;
using (M1Context m1 = new M1Context())
{
for (; ;)
{
try
{
return await (from a in m1.QualityRegisters
where (a.qanClosed == 0)
//orderby a.qanAssignedDate descending, a.qanOpenedDate
orderby a.qanAssignedDate.HasValue descending, a.qanAssignedDate, a.qanOpenedDate
select new QualityRegisterQueue
{
QualityRegisterID = a.qanQualityRegisterID,
JobID = a.qanJobID.Trim(),
JobAssemblyID = a.qanJobAssemblyID,
JobOperationID = a.qanJobOperationID,
PartID = a.qanPartID.Trim(),
PartRevisionID = a.qanPartRevisionID.Trim(),
PartShortDescription = a.qanPartShortDescription.Trim(),
OpenedByEmployeeID = a.qanOpenedByEmployeeID.Trim(),
OpenedByEmployeeName = a.OpenedEmployee.lmeEmployeeName.Trim(),
OpenedDate = a.qanOpenedDate,
PartImage = a.JobAssembly.ujmaPartImage,
AssignedDate = a.qanAssignedDate,
AssignedToEmployeeID = a.qanAssignedToEmployeeID.Trim(),
AssignedToEmployeeName = a.AssignedEmployee.lmeEmployeeName.Trim()
}).ToListAsync();
}
catch (SqlException ex)
{
Debug.WriteLine("SQL Exception number = " + ex.Number);
if (!Enum.IsDefined(typeof(RetryableSqlErrors), ex.Number))
throw new M1Exception(ex.Message, ex);
retryCount++;
if (retryCount > MAX_RETRY) throw new M1Exception(ex.Message, ex); ;
Debug.WriteLine("Retrying. Count = " + retryCount);
Thread.Sleep(ex.Number == (int)RetryableSqlErrors.Timeout ?
longWait : shortWait);
}
}
}
}
}
Редактировать: В основном ищут общее руководство здесь, хотя конкретный пример что делать было бы здорово. Для этих типов операций, когда я загружаю данные, просто ли это, что если мне нужно, чтобы приложение было отзывчивым, мне нужно было создавать несколько потоков? Это общее решение этой проблемы? Разве это не то, чего я ожидаю, когда асинк/ждут решения?
Я дал это попробовать в обоих моих ViewModel и моей DataHelper, но это, похоже, ничего не менять. – MEEECNC