异步调用带有输出参数的方法

本文关键字:参数 方法 输出 调用 异步 | 更新日期: 2023-09-27 18:11:14

是否可以使用TPL Task<TResult>异步调用具有以下签名的线程安全方法并检索布尔返回值和输出参数?

public bool TryGet(T1 criteria,
                   out T2 output)

显然,由于输出参数的关系,我不能使用lambda表达式。另外,我不能通过定义如下的自定义委托并将其传递给Task<TResult>构造函数来解决问题,因为我需要将标准作为构造函数不支持的强类型参数传递。

public delegate TResult Func<T1, T2, TResult>(T1 arg1,
                                              out T2 arg2);

最好的选择是编写一个包装器,如下面异步调用它?

public Tuple<bool, T2> TryGetWrapper(T1 criteria)
{
    T2 output;
    bool result = obj.TryGet(criteria,
                             out output);
    return new Tuple<bool, T2>(result,
                               output);
}

只是看起来有点不优雅,有一点味道。

异步调用带有输出参数的方法

这也是我一直纠结的问题。

我想出了一个类似的解决方案,除了没有使用Tuple,我写了一个简单的包装类,只是为了让事情更容易读。

我也很想看看更好的解决方案,但你的建议似乎和我想到的一样好。

下面是我的包装器类及其用法。这不是对你问题的回答;只是一个建议,(也许)使你的解决方案更容易读。

(尽管我承认Task<TryResult<DateTime>>声明本身可能不被认为是可读的!)

using System;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
    internal class Program
    {
        static void Main()
        {
            string dateString = "Invalid Date";
            var tryParseDateTask = new Task<TryResult<DateTime>>(() =>
            {
                DateTime result;
                if (DateTime.TryParse(dateString, out result))
                    return TryResult<DateTime>.Success(result);
                else
                    return TryResult<DateTime>.Failure();
            });
            tryParseDateTask.Start();
            if (tryParseDateTask.Result.IsSuccessful)
                Console.WriteLine(dateString + " was parsed OK.");
            else
                Console.WriteLine(dateString + " was parsed as " + tryParseDateTask.Result.Value);
        }
    }
    public class TryResult<T>
    {
        public static TryResult<T> Success(T value)
        {
            return new TryResult<T>(value, true);
        }
        public static TryResult<T> Failure()
        {
            return new TryResult<T>(default(T), false);
        }
        TryResult(T value, bool isSuccessful)
        {
            this.value = value;
            this.isSuccessful = isSuccessful;
        }
        public T Value
        {
            get
            {
                return value;
            }
        }
        public bool IsSuccessful
        {
            get
            {
                return isSuccessful;
            }
        }
        readonly T value;
        readonly bool isSuccessful;
    }
}

我认为你的方法已经是最好的了。如果你经常这样做,你可以使用一个助手方法,将带有out参数的委托转换为返回Tuple的委托(或类似于返回TryResult的委托,如马修沃森的回答):

public delegate TResult OutFunc<TIn, TOut, TResult>(TIn input, out TOut output);
public static Func<TIn, Tuple<TResult, TOut>> OutToTuple<TIn, TOut, TResult>(
    OutFunc<TIn, TOut, TResult> outFunc)
{
    return input =>
    {
        TOut output;
        TResult result = outFunc(input, out output);
        return Tuple.Create(result, output);
    };
}