【问题标题】:Asynchronously invoking a method with an output parameter异步调用带有输出参数的方法
【发布时间】:2013-04-29 10:00:32
【问题描述】:

是否可以使用 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);
}

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

【问题讨论】:

    标签: c# task-parallel-library output-parameter


    【解决方案1】:

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

    我想出了一个类似的解决方案,除了使用 Tuple 之外,我编写了一个简单的包装类,只是为了让事情更具可读性。

    我也有兴趣看到任何更好的解决方案 - 但您提出的建议似乎与我提出的任何建议一样好。

    这是我的包装类及其用法的样子。这不是您问题的答案;只是一个建议(也许)使您的解决方案更具可读性。

    (虽然我承认Task&lt;TryResult&lt;DateTime&gt;&gt; 声明本身可能不被认为是那么可读!)

    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;
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      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);
          };
      }
      

      【讨论】:

        猜你喜欢
        • 2019-06-20
        • 1970-01-01
        • 2014-04-23
        • 2023-04-01
        • 1970-01-01
        • 2020-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多