等待同一任务的多个对象的 TaskCompletionSource

TaskCompletionSource for multiple objects awaiting same Task

我想知道在以下示例中使用 TaskCompletionSource class 是否合适:

原始代码/没有 TaskCompletionSource

public async Task GetData() 
{
    if (!IsLoaded) 
    {
        MyList = await Mediator.Send(new GetData());
        IsLoaded = true;
    }
}

此函数在我的 .NET Core Web 应用程序中作为单例范围服务的一部分提供。多个对象可以使用 MyList 中的记录,并且在使用列表之前将等待 GetData() 函数。

从示例函数可以看出,当第一次调用还在等待Mediator请求的结果时,该方法可能会被调用多次。我想要一个允许多个对象等待同一个任务的解决方案。那么为此目的使用 TaskCompletionSource 对象是否合适?

使用 TaskCompletionSource 重构

private TaskCompletionSource getDataTask;

public async Task VerifyDataIsLoaded() 
{
    if (getDataTask == null) 
    {
        getDataTask = new TaskCompletionSource();
        Task.Factory.StartNew(async () => 
        {
            await GetData();
            getDataTask.TrySetResult();
        }
    }
    return getDataTask.Task;
}

private async Task GetData() 
{
    MyList = await Mediator.Send(new GetData());
}

这应该导致第一次调用 VerifyDataIsLoaded() 实例化 TaskCompletionSource getDataTask 对象的实例,在新的线程任务中启动 GetData() 函数,并且 returning getDataTask.Task 属性.

现在,如果在 GetData() 函数等待来自 Mediator 对象的 return 时,任何其他对象调用 VerifyDataIsLoaded(),它们都将等待同一个任务,并防止对 GetData.

的任何冗余调用

想法?? ... 馊主意??更好的方法??

这个的正常模式是 Lazy<Task<T>>,或者 custom AsyncLazy<T> type

private readonly Lazy<Task> getDataTask = new(GetData);
public Task VerifyDataIsLoadedAsync() => getDataTask.Value;

尽管总的来说,我不推荐这种异步初始化API,因为消费者始终记得对其进行初始化。我更喜欢异步工厂模式。