【问题标题】:How to use the Func<Task<T>> Syntax?如何使用 Func<Task<T>> 语法?
【发布时间】:2015-06-02 14:32:19
【问题描述】:

我在另一个答案Best way in .NET to manage queue of tasks on a separate (single) thread 中找到了这门课。

我想尝试一下,但语法对我来说有点奇怪。试图启动一个返回单个 int 的虚拟任务。我无法编译,不知道是什么语法问题。

        m_TaskQueue.Enqueue<int>(
                () => { return 1; }
            );

编译器错误:

无法将 lambda 表达式转换为委托类型 System.Func&lt;System.Threading.Tasks.Task&lt;int&gt;&gt;,因为块中的某些返回类型不能隐式转换为委托返回类型

其他答案的类:

public class TaskQueue
{
    private SemaphoreSlim semaphore;
    public TaskQueue()
    {
        semaphore = new SemaphoreSlim(1);
    }

    public async Task<T> Enqueue<T>(Func<Task<T>> taskGenerator)
    {
        await semaphore.WaitAsync();
        try
        {
            return await taskGenerator();
        }
        finally
        {
            semaphore.Release();
        }
    }
    public async Task Enqueue(Func<Task> taskGenerator)
    {
        await semaphore.WaitAsync();
        try
        {
            await taskGenerator();
        }
        finally
        {
            semaphore.Release();
        }
    }
}

【问题讨论】:

  • 错误编译器在说什么?
  • 你正在传递Func&lt;int&gt;不是 Func&lt;Task&lt;int&gt;&gt;
  • 旁注:您发现的代码不会在单独的线程上安排任务,因此添加同步任务通常毫无意义,因为它们会在当前线程上同步运行。

标签: c#


【解决方案1】:

要添加到建议使用Task.FromResult 创建任务的其他答案,您还可以使用异步 lambda 表达式 - 如果您想在 lambda 表达式的主体中使用 await,这将很有用:

m_TaskQueue.Enqueue<int>(
    async () => { 
        await Task.Delay(1000); // For example
        return 1;
    }
);

【讨论】:

  • 所以不知何故向 lambda 添加 async/await 会将其从 Func&lt;int&gt; 变为 Func&lt;Task&lt;int&gt;&gt;
  • @EhsanSajjad 我认为async lambdas 不是解决方法,但实际上是调用此排队代码的预期方式 - 将同步操作安排到将同步运行它的队列实际上没有太大价值大多数情况下都是线程。
  • @user17753: @user17753: 是的 - 就像在方法声明中添加 async 意味着它必须有一个返回类型 Task&lt;int&gt; 而不是 int (但在方法内,你仍然返回一个int...)请注意,你没有await 任何东西,但如果你不这样做,你会收到警告 - 它是async在这里很重要的上下文关键字。
  • async () =&gt; { return await Task.Run( () =&gt; { return myInt; }); 这样的东西也有意义吗?在返回 myInt 之前我会做很多事情(可能是缓慢的 I/O 等)。
  • @user17753:你为什么要那样做?不要使用Task.Run,只需在 lambda 表达式中使用异步 IO 调用即可。
【解决方案2】:

正如错误试图告诉您的那样,您需要一个返回 Task&lt;T&gt; 的函数。

您可以使用Task.FromResult(1) 创建一个。

【讨论】:

    猜你喜欢
    • 2018-02-16
    • 2019-03-30
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多