Tag: async await

对HttpClient请求进行速率限制的简单方法

我正在使用System.Net.Http中的HTTPClient来对API发出请求。 API限制为每秒10个请求。 我的代码大致如下: List tasks = new List(); items..Select(i => tasks.Add(ProcessItem(i)); try { await Task.WhenAll(taskList.ToArray()); } catch (Exception ex) { } ProcessItem方法做了一些事情,但总是使用以下方法调用API: await SendRequestAsync(..blah) 。 看起来像: private async Task SendRequestAsync(HttpRequestMessage request, CancellationToken token) { token.ThrowIfCancellationRequested(); var response = await HttpClient .SendAsync(request: request, cancellationToken: token).ConfigureAwait(continueOnCapturedContext: false); token.ThrowIfCancellationRequested(); return await Response.BuildResponse(response); } 最初代码工作正常,但是当我开始使用Task.WhenAll时,我开始从API获得“超出速率限制”消息。 如何限制请求的速率? 值得注意的是,ProcessItem可以根据项目进行1-4次API调用。

同步从Web API调用外部api

我需要从我的Web API 2控制器调用外部api,类似于此处的要求: 使用Web API Action中的HttpClient调用外部HTTP服务 但是,上面的解决方案需要在我的api方法的GET调用中添加async关键字,从而使我的调用异步。 我更喜欢用同步方法呈现我的API的客户端,但仍然能够从我自己的api调用外部api(并且需要在我的api返回之前返回)。 有没有办法做到这一点?

何时使用OrderByCompletion(Jon Skeet)和Parallel.ForEach与异步委托

最近,NDC伦敦的Jon Skeet谈到了C#5 async / await,并提出了“ 按完成排序 ”的想法,列出了异步任务。 链接http://msmvps.com/blogs/jon_skeet/archive/2012/01/16/eduasync-part-19-ordering-by-completion-ahead-of-time.aspx 我有点困惑,或者我应该说我不确定这种技术何时更适合使用。 我无法理解这个和下面的例子之间的区别 var bag = new ConcurrentBag(); Parallel.ForEach(myCollection, async item => { // some pre stuff var response = await GetData(item); bag.Add(response); // some post stuff } 或由Stephen Toub解释的ForEachAsync – http://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx 编辑:发现一篇来自Stephen Toub的博客文章解释“按完成排序”“处理完成后的任务”。 值得阅读。 阅读本文后,我可以清楚地了解它的工作原理以及何时使用这种技术。

异步等待最佳实践

我已经掌握了异步等待的概念并且一直在使用它,但确实有一些关于最佳实践的问题。 是否可以在while(条件)循环中使用await来继续获取可能存在的数据,直到while条件发生变化,例如stopProcessingMessages = false。 在诸如winforms的应用程序中,当UI在它的线程上运行时,在按钮单击等操作上使用async / await是相当简单的,但是如果我想在整个控制台应用程序甚至窗口中异步执行呢?服务。 什么是最初开始第一次等待任务的最佳做法,那就是Task.Run(()=> …)? 我希望我在第二个问题中有意义。 我想充分利用异步并充分利用它,但只需要了解如何在它向所有其他异步函数冒泡之前启动初始异步操作。 不使用正确的代码块道歉我在火车上使用我的智能手机。

如果我不等待任务会怎样?

考虑这个例子: var task = DoSomething() bool ready = await DoSomethingElse(); if (!ready) return null; var value = await DoThirdThing(); // depends on DoSomethingElse return value + await task; DoSomething做了一些可能需要一段时间的非常重要的工作,因此我们首先开始它。 与此同时,我们会检查我们是否已准备好使用DoSomethingElse ,如果没有,我们会提前退出。 我们只有在ready 才会调用DoThirdThing ,因为宇宙可能会爆炸。 我们不能使用Task.WhenAll因为DoThirdThing依赖于DoSomethingElse ,我们也不想等待DoSomething因为我们想要尽可能同时调用其他两个方法。 问题是:如果我们还没有ready并提前退出,会发生什么? 它会抛出的任何exception会被SynchronizationContext重新抛出吗? 如果task正常完成,是否存在问题,因为没有人消耗它的价值? 后续行动:有没有一种巧妙的方法来确保等待task ? 如果我们还没ready ,我们可以简单地await task ,但是如果有50个退出条件,那将非常繁琐。 是否可以使用finally块来await task并重新抛出潜在的exception? 如果task正常完成,则会在finally块中再次等待,但这不会导致任何问题吗?

等待任务列表

我正在尝试做这样的事情: foreach (var o in ObjectList) { CalculateIfNeedToMakeTaskForO(o); if (yes) TaskList.Add(OTaskAsync()); } 现在我想等待所有这些任务完成。 除了做 foreach(var o in ObjectList) { Result.Add(“result for O is: “+await OTaskAsync()); } 有什么我能做的吗? (更好,更优雅,更“正确”)

TaskContinuationOptions.RunContinuations异步和Stack Dives

在这篇博客文章中 ,Stephan Toub描述了一个将包含在.NET 4.6中的新function,它为TaskCreationOptions和TaskContinuationOptions枚举增加了另一个名为RunContinuationsAsynchronously 。 他解释说: “我谈到了在TaskCompletionSource上调用{Try} Set *方法的分支,从TaskCompletionSource的Task的任何同步延续都可以作为调用的一部分同步运行。如果我们在这里调用SetResult同时持有锁,那么同步延续关闭该任务将在持有锁的同时运行,这可能会导致非常真实的问题。因此,在持有锁时我们抓住TaskCompletionSource来完成,但是我们还没有完成它,延迟这样做直到锁定已被释放“ 并给出以下示例来演示: private SemaphoreSlim _gate = new SemaphoreSlim(1, 1); private async Task WorkAsync() { await _gate.WaitAsync().ConfigureAwait(false); try { // work here } finally { _gate.Release(); } } 现在假设您有很多对WorkAsync的调用: await Task.WhenAll(from i in Enumerable.Range(0, 10000) select WorkAsync()); 我们刚刚创建了10,000个对WorkAsync的调用,这些调用将在信号量上进行适当的序列化。 其中一个任务将进入关键区域,其他任务将在WaitAsync调用上排队,SemaphoreSlim内部有效地将任务调用完成,当有人调用Release时。 如果Release同步完成了Task,那么当第一个任务调用Release时,它将同步开始执行第二个任务,当它调用Release时,它将同步开始执行第三个任务,依此类推。 如果上面代码的“// work here”部分没有包含任何等待产生的东西,那么我们可能会在这里堆叠潜水并最终可能导致堆栈爆炸。 我很难掌握他谈论同步执行延续的部分。 题 怎么可能导致堆栈潜水? 更重要的是,为了解决这个问题, RunContinuationsAsynchronously会RunContinuationsAsynchronously地做些什么?

Winforms调用异步方法挂起程序

我一直在解决这个问题,但现在我真的想了解出了什么问题。 我有一个相当简单的应用程序(它是youtrack的turtoise SVN插件,但我可以用一个简单的winforms应用程序重现这个问题)。 我有一个异步方法ResolveIssue public async Task ResolveIssue(Issue issue, int revision, string[] pathList) { await Task.Delay(1000); return true; } 我需要做的就是创建一个死锁,在Button事件处理程序中调用这个异步方法,并调用Task.Wait或Task.Result ,就像这样 private void buttonOk_Click(object sender, System.EventArgs e) { var asyncResolvedIssue = api.ResolveIssue(issue, revision, pathList); if (asyncResolvedIssue.Result) {} // <== deadlock! } 现在我明白拥有异步方法并主动等待它是相当奇怪的,但为什么会产生死锁?!

如何将task.Wait(CancellationToken)转换为await语句?

因此, task.Wait()可以转换为await task 。 当然,语义是不同的,但这大致是我将使用Waits将阻塞代码转换为具有Waits的异步代码的方式。 我的问题是如何将task.Wait(CancellationToken)转换为相应的await语句?

异步ShowDialog

我正在使用async / await从数据库异步加载我的数据,在加载过程中,我想弹出一个加载表单,它只是一个带有运行进度条的简单表单,表示有一个正在运行的进程。 加载数据后,对话框将自动关闭。 我怎样才能做到这一点? 以下是我目前的代码: protected async void LoadData() { ProgressForm _progress = new ProgressForm(); _progress.ShowDialog() // not working var data = await GetData(); _progress.Close(); } 更新: 我设法通过更改代码来使其工作: protected async void LoadData() { ProgressForm _progress = new ProgressForm(); _progress.BeginInvoke(new System.Action(()=>_progress.ShowDialog())); var data = await GetData(); _progress.Close(); } 这是正确的方式还是有更好的方法? 谢谢你的帮助。