【问题标题】:Using 'out' within lambdas when creating Tasks via Task Parallel Library通过任务并行库创建任务时在 lambdas 中使用“out”
【发布时间】:2012-12-18 20:51:18
【问题描述】:

我有以下无法编译的代码。我收到错误

不能在匿名方法、lambda 表达式或查询表达式中使用 ref 或 out 参数“messageLockToken”

我承认我是 Lambdas 新手,对解决这个问题有点困惑。有谁知道我如何以编译器可接受的方式表达下面的逻辑?

public T Receive<T>(TimeSpan receiveTimeout, out Guid messageLockToken)
{
    // do work
}

public Task<T> ReceiveAsync<T>(TimeSpan receiveTimeout, out Guid messageLockToken)
{
    Task<T> sendQueueMsgTask = new Task<T>(() => Receive<T>(receiveTimeout, out messageLockToken));
    return sendQueueMsgTask;
}

【问题讨论】:

  • C#,每个 .NET 4.5 的最新实现

标签: c# lambda task-parallel-library


【解决方案1】:

首先,即使编译,您的方法也无法工作。那是因为当你使用new Task() 时,你总是必须在那个Task 上调用Start()(或者,使用Task.Run())。

现在,你不能在这里使用out 参数,因为它没有多大意义。您想立即从方法中返回Task,但这也意味着立即返回Guid。这意味着您对Receive() 的调用无法实际影响out 参数的值。

我认为使用Tuple(如 Rawling 建议的那样)或自定义返回类型是这里的方法:

public Task<Tuple<T, Guid>> ReceiveAsync<T>(TimeSpan receiveTimeout)
{
    return Task.Run(
        () =>
        {
            Guid messageLockToken;
            var result = Receive<T>(receiveTimeout, out messageLockToken);
            return Tuple.Create(result, messageLockToken);
        });
}

这假设您确实想要这样做,请参阅 Stephen Toub 的文章 Should I expose asynchronous wrappers for synchronous methods? 了解为什么这样做可能不是一个好主意。

【讨论】:

    【解决方案2】:

    由于您不能在此处使用 out 参数,因此您可以:

    • 返回Tuple&lt;T, Guid&gt;(或使用自定义泛型类),或
    • 传递Action&lt;Guid&gt; 而不是out Guid(所以你应该调用ReceiveAsync(ts, g =&gt; myGuid = g) 而不是ReceiveAsync(ts, out myGuid)

    (我不认为有任何方法可以解决这个问题,仍然向调用者公开 out 参数;应该在方法返回时填充 out 参数,但这不会是在你的情况下是真的。)

    【讨论】:

    • 我认为您的第二种方法会令人困惑,因为不清楚何时调用 lambda。
    • @svick 我同意,尽管这与Task 的 lambda 允许out 的行为相同:“在任务完成时设置此 guid”。跨度>
    猜你喜欢
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2015-01-14
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    相关资源
    最近更新 更多