使用迭代器等待任务
本文关键字:任务 等待 迭代器 | 更新日期: 2023-09-27 18:05:15
我使用本文中描述的方法在c# 4中使用迭代器等待任务,在没有c# 5的情况下尽可能接近地使用async
和await
关键字进行复制。
我偶然发现了一个问题,我认为这与在c# 5中使用GetResponseAsync()
时似乎经常出现的问题相同,因为每当我尝试使用等效扩展方法时,yield return
跳出我的IEnumerable<Task>
。我没有可用的ConfigureAwait(false)
方法。
有人能想到解决这个问题的方法吗?
我的代码:
/// <summary>
/// Processes the image.
/// </summary>
/// <param name="context">
/// the <see cref="T:System.Web.HttpContext">HttpContext</see>
/// object that provides references to the intrinsic server objects
/// </param>
private /*async*/ void ProcessImageAsync(HttpContext context)
{
this.ProcessImageAsyncTask(context).ToTask();
}
/// <summary>
/// Processes the image.
/// </summary>
/// <param name="context">
/// the <see cref="T:System.Web.HttpContext">HttpContext</see>
/// object that provides references to the intrinsic server objects
/// </param>
/// <returns>
/// The <see cref="IEnumerable{Task}"/>.
/// </returns>
private IEnumerable<Task> ProcessImageAsyncTask(HttpContext context)
{
// Code ommited that works out the url
Uri uri = new Uri(path);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
Task<WebResponse> responseTask = webRequest.GetResponseAsync();
//################################################################//
//The method appears to be jumping out of the method here on yield
//################################################################//
yield return responseTask;
// Code that runs other tasks
yield break;
}
我正在添加相关的扩展方法作为Github Gist,以使问题更可读。
我怀疑问题是使用TaskScheduler.FromCurrentSynchronizationContext
调度延续。添加另一个重载来避免这种情况应该是相当简单的:
public static Task<TResult> ToTask<TResult>(this IEnumerable<Task> tasks, TaskScheduler taskScheduler)
{
var taskEnumerator = tasks.GetEnumerator();
var completionSource = new TaskCompletionSource<TResult>();
// Clean up the enumerator when the task completes.
completionSource.Task.ContinueWith(t => taskEnumerator.Dispose(), taskScheduler);
ToTaskDoOneStep(taskEnumerator, taskScheduler, completionSource, null);
return completionSource.Task;
}
public static Task<TResult> ToTask<TResult>(this IEnumerable<Task> tasks)
{
var taskScheduler = SynchronizationContext.Current == null
? TaskScheduler.Default
: TaskScheduler.FromCurrentSynchronizationContext();
return ToTask<TResult>(tasks, taskScheduler);
}
你的代码会调用另一个重载:
private /*async*/ void ProcessImageAsync(HttpContext context)
{
ProcessImageAsyncTask(context).ToTask(TaskScheduler.Default);
}