代码之家  ›  专栏  ›  技术社区  ›  M.kazem Akhgary

如何处理ContinueWith和WhenAll异常?

  •  -1
  • M.kazem Akhgary  · 技术社区  · 6 年前

    我正在尝试异步加载多个文件,并在加载完每个文件后通知UI,

    _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 创建新任务,但我返回旧任务。

    这是因为 这是一项无效的任务。但是我不知道如何正确返回结果。我不确定它是否安全使用 t.Result 因为它可能会阻塞UI线程?


    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); ;
    })));
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   M.kazem Akhgary    6 年前

    多亏了@Jimi,我才能够通过查看任务状态来解决这个问题。

    loads = (await Task.WhenAll(files.Select(file =>
    {
        return LoadAsync(file).ContinueWith(t =>
        {
            if (t.IsFaulted) NotifyUser(t.Exception.Message, NotifyType.ErrorMessage);
            if (t.IsCanceled) NotifyUser("operation was canceled.", NotifyType.ErrorMessage);
    
            if (t.Status == TaskStatus.RanToCompletion)
            {
                LoadedFiles.Add(file.Path);
                return t.Result;
            }
    
            return null;
        }, scheduler);
    }))).Where(x => x != null).ToArray();