【问题标题】:Task.WhenAny Can this be resolved from a Synchronous Pipeline?Task.WhenAny 这可以从同步管道中解决吗?
【发布时间】:2018-11-28 09:43:00
【问题描述】:

我一直在查看How to call asynchronous method from synchronous method in C#?,以便在非异步函数中解决异步调用。

我可以使用该文章的解决方案 A 来解决我的个人异步任务。但是当单个异步函数本身包含对异步调用数组的调用时,我看不到它是如何完成的。现在它只是在通话中冻结

var result = task.WaitAndUnwrapException();

这就是我所拥有的

public static async Task<List<SearchModel>> GoAsync(SearchContract search, CancellationToken cancellationToken = default(CancellationToken))
        {    
            var taskList = new List<Task<List<SearchModel>>>
            {                    
                SearchRoutine1Async(search, cancellationToken),
                SearchRoutine2Async(search, cancellationToken)
            };

            Task<List<SearchModel>> completedTask = await Task.WhenAny(taskList);

            return completedTask.Result;
        }

一个任务的例子是:

public static async Task<List<SearchModel>> SearchRoutine1Async(SearchContract search, CancellationToken cancellationToken = default(CancellationToken))
        {
            using (DBContext db = new DBContext)
            {
                var searchModels= await db.SearchModel
                    .Where(sm => sm.subKey1 = search.subKey1)
                    .ToListAsync(cancellationToken)
                    .ConfigureAwait(false)
                    ; 

                return searchModels;
            }
        }

来自同步例程的调用如下,它在任务上冻结。WaitAndUnwrapException...:

var task = GoAsync(search);
var result = task.WaitAndUnwrapException();

回顾一下......如果我绕过 GoAsync 例程并单独调用任务......它可以从同步例程中执行此操作:

var task = SearchRoutine1Async(search);
var result = task.WaitAndUnwrapException();

【问题讨论】:

  • 等待Task.WhenAny时不要忘记.ConfigureAwait(false)
  • @KevinGosse 我认为这确实有效。至少现在似乎是。添加到答案,我会接受。

标签: c# async-await task-parallel-library


【解决方案1】:

显然我在

之后缺少 .ConfigureAwait(false)
Task<List<SearchModel>> completedTask = await Task.WhenAny(taskList);

到这个:

Task<List<SearchModel>> completedTask = await Task.WhenAny(taskList).ConfigureAwait(false);

@KevinGrosse 谢谢!

不知道为什么我需要它。在异步管道中运行时不需要。

【讨论】:

  • 这是同步等待任务时已知的死锁情况。只需搜索“deadlock”和“ConfigureAwait”,您就会找到大量资源来解释发生了什么
  • 如果您想要管道使用 TPL 数据流类,如 TransformBlock、ActionBlock。正确编写管道并非易事。或者使用 System.Threading.Channels 类在步骤之间进行通信。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
相关资源
最近更新 更多