c# - 如何在不运行异步方法的情况下对异步方法的任务结果进行排队?

标签 c# asynchronous task task-queue

如果我有一个类包含稍后要执行的任务队列,并且我有一个 async Task<T>方法,如何在不执行该异步方法的情况下将其入队?

我想“延迟”这个任务,并确保调用者看到它稍后运行,就像在方法体中等待它一样。 --- 调用者不应该知道我已经将任务排入队列以备后用。

现在,如果我的队列已满,我将构造并返回一个新的 Task<T>这里没有运行,返回 .Result我的私有(private)异步方法:

public async Task<T> ExecuteAsync<T>(T transaction) {
    if (mustDelay) {
        Task<T> task = new Task<T>(t => executeAsync((T) t).Result, transaction);
        enqueue(task);
        return await task;
    }
    return await executeAsync(transaction);
}

private async Task<T> executeAsync<T>(T transaction) {
    await someWork();
    return transaction;
}

当其他一些任务完成时,我出列并 Start()排队的任务:

dequeuedTask.Start();

这是否确保调用者看到与从方法返回等待结果相同的同步?

最佳答案

这是一个简化的例子:

async Task<T> GetResult<T>()
{
    DoRightAway();
    await DoLater();
    return DoEvenLater();
}

Task<T> task = GetResult<T>();
//task is running or complete

您想推迟 GetResult<T>()通过获取它代表的未完成任务来执行。问题是调用 async方法开始运行它,即使你没有await电话。该方法运行到第一个 await ,即 await DoLater()在这个例子中。

了解为什么您无法获得 async 代表的任务方法而不运行它,请考虑以下三个概念:

  • A Func对象表示未开始的计算。
  • 一个新的Lazy对象表示将运行一次的未启动计算。
  • 调用 async方法代表最终的计算。

这些概念中的每一个都是不同的,但它们可以相互组合成组合表示。我们的GetResult<T>() call 是第三个概念的一个例子。当结果准备好时,它将通过 await 继续执行。或 ContinueWith .在我们的例子中,我们甚至不想开始执行。相反,我们需要将第一个和第三个概念组合成一个表示。也就是说,我们需要一个未启动计算(Func),当它最终开始(async 方法调用)时,最终将完成。

将这种见解付诸实践,我们通过包装 GetResult<T>() 解决了我们的问题在 Func 中的 body .

Func<Task<T>> GetFactory()
{
    return async () =>
    {
        DoRightAway();
        await DoLater();
        return DoEvenLater();
    }
}

我们调用这个新方法来获取函数:

Func<Task<T>> function = GetFactory();

恭喜!我们没有运行就得到了任务!好吧,有点。我们有一个包装(尚未创建)任务的函数。当准备好创建和运行任务时,我们调用函数:

Task<T> task = function();

我们确保任务完成并获得结果:

T result = await task;

关于c# - 如何在不运行异步方法的情况下对异步方法的任务结果进行排队?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46896387/

相关文章:

c# - 如何使用.net core Entity Framework 调用返回list<int>的存储过程

c# - Automapper 使用子对象覆盖列表中缺少的源属性

javascript - 如何使用多个 XMLHttpRequest.responseText 值?

c# - 为什么要对 QueueBackgroundWorkItem 使用异步?

javascript - 如何使 forEach 循环等待正则表达式替换?

c# - System.ArgumentException : Object is not an ADODB. RecordSet 或 ADODB.Record

c# - ASP.Net Web 应用程序连接到主机 SQL 数据库

Gradle-如何在Gradle中添加一些延迟暂停挂起

parallel-processing - Gradle : Run subproject's tasks in parallel

multithreading - iTask - 如何使用变量作为任务过程的参数