什么';TaskCompletionSource<;部署目录>;

本文关键字:gt 部署 TaskCompletionSource 什么 lt | 更新日期: 2023-09-27 18:26:29

我正在使用Nuget包System.Threading.Tasks for Silverlight4(来自Mono的端口)。我不断获取以下内容的InvalidOperationException("底层任务已经处于三种最终状态之一:RanToCompletion、Faulted或Canceled。"):

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

我在WebClient中使用了相同的模式,它工作得很好(但我不必显式地Start()任务——但是我没有用单端口版本的任务并行库(用于Silverlight)测试WebClient。我想我应该这么做。。。

什么';TaskCompletionSource<;部署目录>;

您正在TaskCompletionSource上调用Start,而TCS任务已经启动,在出现此异常的情况下,它也已经完成。通常,您希望设计像DownloadCatalogAsTask这样的方法来返回已经启动的Task实例,并且调用者可以期望它们被启动,并避免自己调用Start。

其他建议:

  1. 我会考虑将该方法重命名为DownloadCatalogAsync,以符合.NET4.5的命名准则
  2. 我不会通过操作<>到async方法中。返回Task的全部意义在于,您可以使用熟悉的模式(如C#5.0中的显式ContinueWith或await关键字)来连锁continuation。在这里,你发明了自己的方法

我也遇到了同样的问题。即Silverlight 4上的Mono TPL;在completionSource.SetResult()处引发异常。

当我使用completionSource.TrySetResult()时,这个问题得到了解决。