0

この記事Await Tasks in C#4 using Iteratorsasync here で説明されている方法を使用して、C#5 を使用せずにandawaitキーワードをできるだけ厳密に複製しています。

同等の拡張メソッドGetResponseAsync()を使用しようとするたびに. ただし、利用できる方法はありません。yield returnIEnumerable<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として追加しています。

4

1 に答える 1

0

問題は、継続がを使用してスケジュールされていることだと思い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);
}
于 2013-03-22T19:04:06.330 に答える