C# 使用输出参数异步调用方法

C# 使用输出参数异步调用方法,c#,task-parallel-library,output-parameter,C#,Task Parallel Library,Output Parameter,是否可以使用TPL任务异步调用具有以下签名的线程安全方法,并检索布尔返回值和输出参数 public bool TryGet(T1 criteria, out T2 output) 显然,由于输出参数的原因,我不能使用lambda表达式。此外,我无法通过定义如下的自定义委托并将其传递给任务构造函数来解决问题,因为我需要将条件作为构造函数不支持的强类型参数传递 public delegate TResult Func<T1, T2, TResult>

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

public bool TryGet(T1 criteria,
                   out T2 output)
显然,由于输出参数的原因,我不能使用lambda表达式。此外,我无法通过定义如下的自定义委托并将其传递给
任务
构造函数来解决问题,因为我需要将条件作为构造函数不支持的强类型参数传递

public delegate TResult Func<T1, T2, TResult>(T1 arg1,
                                              out T2 arg2);
public委托TResult Func(T1 arg1,
输出t2arg2);
写一个像下面这样的包装器并异步调用它是最好的选择吗

public Tuple<bool, T2> TryGetWrapper(T1 criteria)
{
    T2 output;

    bool result = obj.TryGet(criteria,
                             out output);

    return new Tuple<bool, T2>(result,
                               output);
}
公共元组tryGatheraper(T1标准)
{
T2输出;
bool结果=目标测试集(标准,
输出);
返回新的元组(结果,
输出);
}

只是看起来有点不雅观,有点不雅。

这也是我一直在努力解决的问题

我提出了一个类似的解决方案,除了我编写了一个简单的包装器类,而不是使用元组,只是为了让事情更具可读性

我也有兴趣看到更好的解决方案——但你的建议似乎和我提出的任何方案一样好

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

(尽管我承认,
任务
声明本身可能不那么可读!)

使用系统;
使用System.Threading.Tasks;
命名空间控制台应用程序1
{
内部课程计划
{
静态void Main()
{
string dateString=“无效日期”;
var tryParseDateTask=新任务(()=>
{
日期时间结果;
if(DateTime.TryParse(dateString,out结果))
返回TryResult.Success(结果);
其他的
返回TryResult.Failure();
});
tryParseDateTask.Start();
if(tryParseDateTask.Result.issusccessful)
WriteLine(dateString+“已解析为OK”);
其他的
WriteLine(dateString+”被解析为“+tryParseDateTask.Result.Value”);
}
}
公共类TryResult
{
公共静态TryResult成功(T值)
{
返回新的TryResult(值,true);
}
公共静态TryResult失败()
{
返回新的TryResult(默认值(T),false);
}
TryResult(T值,布尔成功)
{
这个值=值;
this.issucessful=issucessful;
}
公共价值
{
得到
{
返回值;
}
}
公共事业成功
{
得到
{
返回成功;
}
}
只读T值;
只读布尔成功;
}
}

我认为你的方法几乎是你能做到的最好的方法。如果您经常这样做,您可以使用助手方法将带有
out
参数的委托转换为
Tuple
-返回委托(或类似于
TryResult
-返回的委托,如Matthew Watson的回答所示):

public委托TResult outpunc(TIn输入,out TOut输出);
公共静态函数OutToTuple(
流出口(流出口)
{
返回输入=>
{
兜售产量;
TResult result=outpunc(输入,输出);
返回Tuple.Create(结果,输出);
};
}
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;
    }
}
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);
    };
}