2013-05-22 24 views
6

Asynchronous Görevler ve Varlık Çerçevesi (Mono ile Linux (RHEL) altında çalıştırmak amacıyla, ancak diğer bir zorluktur) kullanan basit bir C# konsol uygulaması yazıyorum. .NET 4.0'ı hedeflediğimi unutmayın, bu yüzden await yerine .ContinueWith() kullanıyorum.Genel Üzerinde Belirsiz Çağırma ContinueWith

using System; 
using System.Linq; 
using System.Threading.Tasks; 

namespace MonoEF 
{ 
    class Program 
    { 
     private static Model.NorthwindEntities _db = new Model.NorthwindEntities(); 

     static void Main(string[] args) 
     { 
      try 
      { 
       GetCustomerNamesAsync().ContinueWith(t => { 
        if (t.IsFaulted) Console.WriteLine(t.Exception.Flatten.ToString); 
         else if (t.IsCompleted) foreach (string result in t.Result) Console.WriteLine(result); 
        }); 

       Console.ReadLine(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 
     } 

     private static Task<string[]> GetCustomerNamesAsync() 
     { 
      return Task.Factory.StartNew(() => (from c in _db.Customers select c.ContactName).Distinct().ToArray()); 
     } 

    } 
} 

Sorun .ContinueWith() aşağıdaki hatayı alıyorum geçerli::

Ambiguous Invocation: 
    System.Threading.Tasks.Task.ContinueWith(System.Action<System.Threading.Tasks.Task<string[]>>) (in class Task<string[]>) 
    System.Threading.Tasks.Task.ContinueWith(System.Action<System.Threading.Tasks.Task>) (in class Task) 
match 

Bu, artı bir Northwind veritabanı EF DB modeli uygulamanın UYULMASINA

Bana göre, çağrının belirsiz olmaması gerekir, derleyici genel olmayan Görev üzerinde genel Görev tercih etmelisiniz, özellikle GetCustomerNamesAsync() çıktısı olduğu gibi. Ancak, bir VB.NET geliştiricisi olarak, bu durumda muhtemelen Option Infer güveniyorum.

Derleyiciye C# 'da kullanmak istediğimi hangi çağrının bildiğini açıkça bildirmek için nasıl giderim?

cevap

10

böyle açıkça lambda parametre türünü belirten deneyin:

.ContinueWith((Task<string[]> t) => { ... }) 

bunu çağırırız yolu ile bu sorun Task<TResult> ve Task (onun temel sınıf) de neredeyse görünen bir ContinueWith yöntemine sahip olmasıdır aynı:

Task<TResult>.ContinueWith(Action<Task<TResult>> action) 
Task<TResult>.ContinueWith(Action<Task> action) //inherited from `Task` 

action giriş türünü belirten olmadan, derleyici istediğiniz aşırı hangi belirleyemez. action lambda'nın giriş parametre türünü açıkça sağlayarak bu belirsizliği giderir. derleyici Action<Task<TResult>> action alır sürümü varsayalım eğer


Kesinlikle güzel olurdu. Belki başka birinin bu tür davranışları nasıl alacağı hakkında bir fikri vardır? kuşaklar için


... yorumlarında

Eğer MCattle o sadece yüzünden lambda içinde bir yöntem çağrısı eksik parantez ile ilgili bazı derleyici gariplik bu sorunla karşılaşmış olduğunu bulduğunu göreceksiniz . Genel olarak, lambda'yı ContinueWith'a geçirirken Task<TResult> türünü açıkça belirtmeniz gerekmemelidir.

+2

Beni doğru çözüme yönlendirdiniz. Açıkça bildiren '.ContinueWith ((Görev t) => {...})' sonra bir sonraki soruyu, 'Console.WriteLine (t.Exception.Flatten.ToString) '' yerine Console.WriteLine çağırıyordu. (t.Exception.Flatten(). .ToString()) '. Bunu düzelttikten sonra, açık lambda parametre bildirimini kaldırabiliyordum ve derleyici mutluydu. – MCattle

+1

@MCattle Buradaki eksik parantezlerin, derleyicinin iki aşırı yüklenme arasında karar verememesi ilginçtir. Kendi cevabımdan biraz şüpheliydim, çünkü lambda girdi türüne sayısız defa “ContinueWith” kullanıyorum. Eksik parantezlerin neden farkı yaratacağını açıklayamıyorum. –

+1

Bana göre bir anlam ifade ediyor, çünkü aşırı yüklenme kullanımdan kaynaklanıyor ve kullanımda bir sözdizimi hatası varsa, doğru aşırı yüke ulaşılamıyor. – MCattle

İlgili konular