我有一个从SQLite数据库获取一些数据的应用程序。例如,我有一种类似于以下方法的方法:
public async Task<IEnumerable<TaskItem>> GetAllAsync()
{
using (var context = new NotesContext())
{
try
{
return await context
.Tasks
.ToListAsync();
}
catch (Exception)
{
return Enumerable.Empty<TaskItem>();
}
}
}
我从页面加载时绑定的命令中调用此方法:
LoadedCommand = new RelayCommand<TaskItemViewModel>
((task) => GetAllTasksAsync(task));
该命令调用的方法:
public async void GetAllTasksAsync(TaskListItemViewModel taskList)
{
ShowTaskListViewProgressRing = true;
Tasks.Clear();
TaskAutoSuggestBoxItems.Clear();
var response = await _dataService
.TaskService
.GetAllAsync()
.ConfigureAwait(false);
var tasks = _mapper.Map<List<TaskItemViewModel>>(response);
if (tasks.Count > 0)
{
var mainTasks = tasks
.Where(t => t.ParentTask == null);
mainTasks.ForEach(t =>
{
if (!tasks.Any(st => st.ParentTask == t.TaskID))
return;
t.SubTasks = new ObservableCollection<TaskItemViewModel>(
tasks
.Where(st => st.ParentTask == t.TaskID)
.OrderBy(st => st.Position));
});
Tasks.AddRange(mainTasks);
TaskAutoSuggestBoxItems
.AddRange(_mapper.Map<IEnumerable<ItemModel>>(mainTasks.OrderBy(t => t.Title)));
}
CurrentTaskList = taskList;
ShowTaskListViewProgressRing = false;
}
如果我没记错,GetAllTasksAsync
被UI线程调用,但是当到达GetAllAsync().ConfigureAwait(false)
时它退出上下文,然后GetAllAsync
在线程池上下文中运行并在完成后返回UI线程并更新视图属性。
这种方法正确吗?
答案 0 :(得分:4)
这种方法正确吗?
捕获异常并假装什么都没有发生,这不是最佳做法:
catch (Exception)
{
return Enumerable.Empty<TaskItem>();
}
如果GetAllAsync()
无法以有意义的方式处理异常,则最好避免捕获任何异常,并由调用方处理。或者,您可能想记录一个错误,然后重新引发异常:
public async Task<IEnumerable<TaskItem>> GetAllAsync()
{
using (var context = new NotesContext())
{
try
{
return await context
.Tasks
.ToListAsync();
}
catch (Exception ex)
{
//log ex...
throw;
}
}
}
此外,不返回诸如GetAllTasksAsync
之类的值的异步方法应返回Task
而不是void
:
public async Task GetAllTasksAsync(TaskListItemViewModel taskList){ ... }
否则,当您致电时,您将无法等待。
您关于捕获SynchronizationContext
和ConfigureAwait
的假设是正确的。