2013-04-29 48 views
4

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

只是看起來有點不雅,並有一點點的味道。

回答

4

這是我也摔跤的東西。

我想出了一個類似的解決方案,除了不使用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; 
    } 
} 
+0

感謝。只是想知道我是否錯過了一些明顯的東西。 – 0b101010 2013-04-29 17:57:50

1

我覺得你的做法是相當多的,你能做的最好的。如果你經常這樣做,你可以用它轉換成一個代表與out參數爲Tuple -returning委託(或類似TryResult -returning,如馬修·沃森的回答)一個輔助方法:

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