Task<T> вернуть null, не прерывая задачу

177
05 февраля 2018, 02:44

Одна задача, ожидает выполнение другой задачи, как только возвращаем null из ожидаемой задачи, происходит прерывание выполнения другой.

Как вернуть null из Task<T>, при этом не прервать выполнение родительского Task<T>, и продолжить выполнение в штатном режиме?

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
    class Program
    {
        public class TaskOperation
        {
            public bool GetNUll { get; set; }
        }
        public class SomeTasks
        {
            public async Task<ObservableCollection<TaskOperation>> GetAllTasks()
            {
                ObservableCollection<TaskOperation> taskOperations = new ObservableCollection<TaskOperation>();
                for (int i = 0; i < 120; i++)
                {
                    taskOperations.Add(new TaskOperation { GetNUll = i % 2 == 0 });
                }
                int t = 0;
                foreach (var taskOperation in taskOperations)
                {
                    if (!(await GetTask(taskOperation)).GetNUll)
                    {
                        Console.WriteLine($"{t}");
                    }
                }
                return taskOperations;
            }
            public Task<TaskOperation> GetTask(TaskOperation operation)
            {
                return operation.GetNUll ? null : Task.Factory.StartNew(() => operation);
            }
        }
        static void Main(string[] args)
        {
            SomeTasks someTasks = new SomeTasks();
            Task.Run(async () => await someTasks.GetAllTasks());
            Console.Read();
        }
    }
}

Данная задача будет прервана на первой же итерации цикла.

Answer 1

Поглядим на код:

async Task ParentTask()
{
    await ChildTask(); // ожидаем Task<T>, всё хорошо
    await ChildTaskNull(); // await null - ошибка
}
Task<string> ChildTask()
{
    return Task.FromResult<string>(null);
}
Task<string> ChildTaskNull()
{
    return null;
}

Смотрим что тут происходит:

У нас есть родительская функция и 2 дочерние. В родительской мы сначала вызываем ChildTask(), который возвращает экземпляр Task<string>, который мы можем ожидать. Потому await ChildTask(); работает нормально.

Далее, ChildTaskNull() возвращает NULL, но NULL - это не экземпляр задачи, это просто пустой указатель. потому await ChildTaskNull(); превращается в await null, что и порождает исключение в родительской задаче.

Как вывод, если ваша функция НЕ асинхронная и просто возвращает Task<T>, и вам надо вернуть null как результат операции, используйте return Task.FromResult<T>(null) или Task.FromResult((T)null)

READ ALSO
сброс цикла по алфавиту

сброс цикла по алфавиту

Уже спрашивал этот вопросно все-таки есть одна проблема

196
Как скомпилировать все проекты солюшена в один .EXE?

Как скомпилировать все проекты солюшена в один .EXE?

Есть солюшен (Solution)В нем 4 проекта

180
C# TCP Отправить hex

C# TCP Отправить hex

Как отправить в C# hex а не string на tcp? Использую для проверки програму-клиент-сервер и если конвертировать string в байты то эта программа получит...

167
Выделение ячейки DataGridView

Выделение ячейки DataGridView

Написал вот такой код:

195