什么';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上调用Start,而TCS任务已经启动,在出现此异常的情况下,它也已经完成。通常,您希望设计像DownloadCatalogAsTask这样的方法来返回已经启动的Task实例,并且调用者可以期望它们被启动,并避免自己调用Start。
其他建议:
- 我会考虑将该方法重命名为DownloadCatalogAsync,以符合.NET4.5的命名准则
- 我不会通过操作<>到async方法中。返回Task的全部意义在于,您可以使用熟悉的模式(如C#5.0中的显式ContinueWith或await关键字)来连锁continuation。在这里,你发明了自己的方法
我也遇到了同样的问题。即Silverlight 4上的Mono TPL;在completionSource.SetResult()
处引发异常。
当我使用completionSource.TrySetResult()
时,这个问题得到了解决。