2012-03-02 8 views
0

Silverlight 4(Monoのポート)にNugetパッケージSystem.Threading.Tasksを使用しています。次のために:TaskCompletionSource <DeploymentCatalog>の何が問題になっていますか?

var tasks = new Task<DeploymentCatalog>[2]; 

//Catalog the XAP downloaded by the Application Loader, the BiggestBox Index: 
var uri0 = new Uri(Application.Current. 

Host.InitParams["LoaderInfoXapPath"], UriKind.Relative); 
tasks[0] = CompositionUtility.DownloadCatalogAsync(uri0); 

//Catalog the XAP with the BiggestBox Index Part: 
var uri1 = new Uri(Application.Current 
    .Host.InitParams["BiggestBoxIndexXapPath"], UriKind.Relative); 
tasks[1] = CompositionUtility.DownloadCatalogAsync(uri1); 

//tasks did not run by default... 
//tasks[0].Start(); 
//tasks[1].Start(); 

Task.WaitAll(tasks); 

this.AddToAggregateCatalog(tasks[0].Result); 
this.AddToAggregateCatalog(tasks[1].Result); 

base.Compose(); 
DownloadCatalogAsyncがある

/// <summary> 
/// Downloads the catalog 
/// in a <see cref="System.Threading.Task"/>. 
/// </summary> 
/// <param name="location">The location.</param> 
/// <param name="downloadCompleteAction">The download complete action.</param> 
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", 
    Justification = "Reliable disposal depends on callers.")] 
public static Task<DeploymentCatalog> DownloadCatalogAsync(Uri location) 
{ 
    return DownloadCatalogAsTask(location, null); 
} 

/// <summary> 
/// Downloads the catalog 
/// in a <see cref="System.Threading.Task"/>. 
/// </summary> 
/// <param name="location">The location.</param> 
/// <param name="downloadCompleteAction">The download complete action.</param> 
/// <remarks> 
/// For details, see the “Converting an Event-Based Pattern” section in 
/// “Simplify Asynchronous Programming with Tasks” 
/// by Igor Ostrovsky 
/// [http://msdn.microsoft.com/en-us/magazine/ff959203.aspx] 
/// </remarks> 
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", 
    Justification = "Reliable disposal depends on callers.")] 
public static Task<DeploymentCatalog> DownloadCatalogAsync(Uri location, 
    Action<object, AsyncCompletedEventArgs> downloadCompleteAction) 
{ 
    var completionSource = new TaskCompletionSource<DeploymentCatalog>(); 
    var catalog = new DeploymentCatalog(location); 

    catalog.DownloadCompleted += (s, args) => 
    { 
     if(args.Error != null) completionSource.SetException(args.Error); 
     else if(args.Cancelled) completionSource.SetCanceled(); 
     else 
     { 
      completionSource.SetResult(s as DeploymentCatalog); //exception thrown here 
      if(downloadCompleteAction != null) 
       downloadCompleteAction.Invoke(s, args); 
     } 
    }; 

    catalog.DownloadAsync(); 

    return completionSource.Task; 
} 
:私は(「RanToCompletion、フォルト発生、またはキャンセル。根底にあるタスクは3つの最終状態のいずれかに既に存在する」) InvalidOperationExceptionを得続けます

私はWebClientと同じパターンを使用していますが、これはうまくいきます(しかし、私はStart()タスクを明示的にする必要はありません)。しかし、私はWebClientをモノポートのバージョンのタスクパラレルライブラリ(Silverlight用)でテストしませんでした。私はそれをする必要があります...

答えて

3

あなたはTaskCompletionSourceでStartを呼び出しています.TCS Taskは既に開始されています。この例外が発生した場合、既に完了しています。一般に、既に開始されたタスクインスタンスを返すためにはDownloadCatalogAsTaskのようなメソッドを設計し、呼び出し元はそれらを開始し、Startを呼び出さないようにしたいと考えています。

カップル他の提案は:

  1. 私は、.NET 4.5の命名ガイドラインに合わせてDownloadCatalogAsyncにメソッドの名前を変更検討します。
  2. 私は、アクション<を非同期メソッドに渡しません。タスクを返すことの全ポイントは、C#5.0の明示的なContinueWithやawaitキーワードのような使い慣れたパターンを使用してコンティニュイションを連鎖できるようにすることです。ここではあなた自身のアプローチを発明しています。
+0

私はこれらの新しい4.5の慣例を心に留めていきます。私はTPLのMonoポートでSilverlight 4を使用していることに言及しませんでした。残念ながら、私は 'Start()'を明示的に呼び出さなければいけません。さもなければ、タスクは 'WaitingForActivation'を返します---この予期しない動作はこのモノと関係しますか? – rasx

+0

@rasx Startを呼び出す必要はありません。タスクを返すメソッドの中でタスクを開始することを確認してください。タスクを開始する必要はありません。動作が進むにつれて、それはSilverlight + Mono TPLライブラリで取らなければならなかったアプローチのためです。 .NET 4 TPLでは、単にTask.Factory.StartNewを使用する可能性が高くなります。 –

0

私は同じ問題を抱えていました。 Silverlight 4のMono TPL。例外はcompletionSource.SetResult()にスローされます。

これは代わりにcompletionSource.TrySetResult()を使用したときに解決されました。

関連する問題