Я пытаюсь загрузить несколько файлов асинхронно и сообщать пользовательскому интерфейсу, когда загружается каждый файл,
_loadCancellationTokenSource = new CancellationTokenSource();
TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
var files = await picker.PickMultipleFilesAsync();
LoadedFiles.Clear();
loads = await Task.WhenAll(files.Select(file =>
{
var load = LoadAsync(file);
load.ContinueWith(t =>
{
if (t.IsCompleted) LoadedFiles.Add(file.Path);
if (t.IsFaulted) NotifyUser(t.Exception.Message, NotifyType.ErrorMessage);
if (t.IsCanceled) NotifyUser("operation was canceled.", NotifyType.ErrorMessage);
}, scheduler);
return load;
}));
private Task<Foo> LoadAsync(StorageFile file)
{
// exception may be thrown inside load
return Load(file, _loadCancellationTokenSource.Token);
}
Проблема в том, что при возникновении исключения оно не обрабатывается.Я знаю почему, потому что ContinueWith
создает новую задачу, но я возвращаю старую.
Это потому, что ContinueWith
- пустая задача.но я не знаю, как правильно вернуть результат.Я не уверен, безопасно ли использовать t.Result
, потому что это может заблокировать поток пользовательского интерфейса?
PS, я пробовал этот код, но я получаю a task was cancelled exception
, и приложение вылетает, даже если яне отменяя никаких задач.только несколько исключений выбрасываются для загрузки некоторых файлов.
load = (await Task.WhenAll(files.Select(file =>
{
var load = LoadAsync(file);
load.ContinueWith(t =>
{
if (t.IsFaulted) NotifyUser(t.Exception.Message, NotifyType.ErrorMessage);
if (t.IsCanceled) NotifyUser("operation was canceled.", NotifyType.ErrorMessage);
}, _loadCancellationTokenSource.Token, TaskContinuationOptions.NotOnRanToCompletion, scheduler);
return load.ContinueWith(t =>
{
LoadedFiles.Add(file.Path);
return (file, t.Result);
}, _loadCancellationTokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, scheduler); ;
})));