【问题标题】:Task.WhenAny to Grab Only Task that resolves the FastestTask.WhenAny 只抓取解决最快的任务
【发布时间】:2018-11-28 07:14:52
【问题描述】:

我有两个异步方法都返回一个列表。他们都以不同的方式搜索记录,我需要他们都并行运行,我只关心首先完成的任务。如果可能,应取消另一个。

我认为我应该使用 Task.WhenAny 但似乎没有正确执行。下面的 GoAsync 实现不返回任何记录,它在 await Task.WhenAny(taskList) 行跳出例程(无错误)。我没有得到结果,等等。我怎样才能得到结果?我这样做对吗?

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

            taskList.Add(new Task(async () => await SearchRoutine1Async(search, cancellationToken)));
            taskList.Add(new Task(async () => await SearchRoutine2Async( search, cancellationToken)));

            Task completedTask = await Task.WhenAny(taskList);
        }

异步例程是这样的:

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

                return searchModels;
            }
        }

当我尝试单独运行这些任务时:它工作正常。

var callTask = Task.Run(() => SearchRoutine1Async(search));
callTask.Wait();
var list1 = callTask.Result;

var callTask2 = Task.Run(() => SearchRoutine2Async(search));
callTask2.Wait();
var list2 = callTask.Result;

[更新]: 我已将我的 GoAsync 更改为:根据以下答案之一:(但它仍然无法正常工作)

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

我从 SYNCHRONOUS 例程中调用例程:

var result = GoAsync(search);

请注意,我深陷于例行程序中,我需要并行运行这些任务以获得竞争结果。那个例程作为一个签名 私有静态无效 DoVariousCalucualtions() {}

【问题讨论】:

  • completedTask 转换为Task&lt;List&lt;SearchModel&gt;&gt; ??为什么async void????
  • 任务(仍然)不是线程并且异步不是并行的:wintellect.com/…code-maze.com/csharp-delegates
  • 它在 await Task.WhenAny(taskList) 行跳出了例程(没有错误) 好吧,你让它异步了??????
  • @ta.speot.is ...好吧,如果我在那之后添加一行代码 await Task.WhenAny(taskList) 行...就像 var result = completedTask.Result 它永远不会到达那一行要么......它只是跳出常规。
  • @user1161137 async void GoAsync 是一个错误,应该是async Task GoAsync()async void 仅适用于事件处理程序。 async void 方法无法等待,并且在应用程序或请求终止时可能仍在运行。如果您希望它异步运行,请使用Task.WaitAny

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


【解决方案1】:

你不需要创建new Task,异步方法会返回一个任务。

public static async Task 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);
    // use competedTask.Result here (safe as you know task is completed)
}

问题更新后:

要获得结果,您需要等待函数完成。

var result = await GoAsync();

但是您提到此调用位于具有void 签名的同步函数的深处,并且您没有使用 ASP.Net Core。这意味着您需要从控制器操作开始使整个“方法管道”异步。 如果你使用GoAsync().Result;,你最终会陷入僵局,你已经经历过的行为......

【讨论】:

  • 这对我不起作用...我没有完成任务...我尝试在 WhenAny 之后执行 var result = completedTask.Result... 但它永远不会到达代码行..它只是在点击 Task> completedTask = await Task.WhenAny(taskList); 后存在
  • @user1161137,点击await Task.WhenAny...后退出是async-await的正确行为,如果你调试代码,在var result = completedTask.Result;行下一个断点并在调试模式下运行应用程序。如果“常规”方法正常工作,则应点击断点。
  • 所以我将签名更改为 public static async Task> GoAsync(...) 并在 WhenAny 之后添加了该行,但它没有达到该断点。我似乎仍然无法得到实际结果。 GoAsync 被同步例程调用,这就是为什么我首先尝试使用 VOID 的 GoAsync。您能否修复您的示例,以便我可以更好地理解这一点?
  • @user1161137,展示您如何调用GoAsync 方法以及您在什么环境中执行代码?如果您不在 ASP.NET Core 应用程序中执行 GoAsync().Result,您可能会遇到死锁。
  • 我已经根据我正在做的事情更新了我的部分。仍然无法得到结果。这不是 asp.net 核心...只是 asp.net。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-15
相关资源
最近更新 更多