Tag: async await

将ThreadStatic变量与async / await一起使用

使用C#中的新async / await关键字,现在会对使用ThreadStatic数据的方式(以及何时)产生影响,因为回调委托在不同的线程上执行,同时启动了async操作。 例如,以下简单的控制台应用程序: [ThreadStatic] private static string Secret; static void Main(string[] args) { Start().Wait(); Console.ReadKey(); } private static async Task Start() { Secret = “moo moo”; Console.WriteLine(“Started on thread [{0}]”, Thread.CurrentThread.ManagedThreadId); Console.WriteLine(“Secret is [{0}]”, Secret); await Sleepy(); Console.WriteLine(“Finished on thread [{0}]”, Thread.CurrentThread.ManagedThreadId); Console.WriteLine(“Secret is [{0}]”, Secret); } private static async Task Sleepy() { Console.WriteLine(“Was […]

定制等待傻瓜

在Async / Await FAQ中 ,Stephen Toub说: 等待是暴露GetAwaiter方法的任何类型,该方法返回有效的awaiter 。 … awaiter是从等待的GetAwaiter方法返回的任何类型,并且符合特定模式。 因此,为了成为awaiter ,类型应该: 实现INotifyCompletion接口。 提供名为IsCompleted的布尔属性。 提供一个无参数的GetResult方法,该方法返回void或TResult 。 ( 我现在忽略了ICriticalNotifyCompletion 。 ) 我知道我提到的页面有一个示例,显示编译器如何转换等待操作,但我很难理解。 当我等待等待 时 , 何时检查IsCompleted ? 我应该在哪里设置它? 何时被OnCompleted调用? 哪个线程调用OnCompleted ? 我看到了直接调用OnCompleted的continuation参数和在不同示例中使用Task.Run(continuation)的示例,我应该选择哪个以及为什么?

调用等待GetFileAsync()永远不会返回,应用程序在WinRT应用程序中挂起

我试图在应用程序启动时加载和读取设置文件,大约90%的时间, await GetFileAsync(“filename.xml”); 永远不会返回,因此,悬挂应用程序。 大约四分之一的时间,如果我单步执行代码,它实际上将返回并读取文件。 这是代码的一个非常简化的版本: App.xaml.cs: protected override void OnLaunched(LaunchActivatedEventArgs args) { FileLoader.Load().Wait(); // File-load dependent stuff } FileLoader.cs: public async static Task Load() { StorageFolder folder = ApplicationData.Current.LocalFolder; StorageFile file; bool fileExists = true; try { // The following line (often) never returns file = await folder.GetFileAsync(“filename.xml”); { catch { fileExists = false; […]

HttpClient – 发送一批请求

我想迭代一批请求,使用HttpClient类将它们中的每一个发送到外部API。 foreach (var MyRequest in RequestsBatch) { try { HttpClient httpClient = new HttpClient(); httpClient.Timeout = TimeSpan.FromMilliseconds(5); HttpResponseMessage response = await httpClient.PostAsJsonAsync(string.Format(“{0}api/GetResponse”, endpoint), myRequest); JObject resultResponse = await response.Content.ReadAsAsync(); } catch (Exception ex) { continue; } } 这里的上下文是我需要设置一个非常小的超时值,所以如果响应花费的时间超过了那个时间,我们只需得到“任务被取消”exception并继续迭代。 现在,在上面的代码中,注释这两行: HttpResponseMessage response = await httpClient.PostAsJsonAsync(string.Format(“{0}api/GetResponse”, endpoint), myRequest); resultResponse = await response.Content.ReadAsAsync(); 迭代结束得非常快。 取消注释,然后重试。 这需要很多时间。 我想知道使用await调用PostAsJsonAsync / […]

如何避免使用异步void事件处理程序重入?

在WPF应用程序中,我有一个通过网络接收消息的类。 每当所述类的对象收到完整消息时,就会引发一个事件。 在应用程序的MainWindow中,我有一个订阅该事件的事件处理程序。 保证在应用程序的GUI线程上调用事件处理程序。 每当调用事件处理程序时,都需要将消息的内容应用于模型。 这样做可能非常昂贵(在当前硬件上> 200ms)。 这就是使用Task.Run将应用消息卸载到线程池的原因。 现在,可以非常接近地接收消息,因此可以在仍在处理先前的更改时调用事件处理程序。 确保消息仅在一次应用时最简单的方法是什么? 到目前为止,我已经提出以下建议: using System; using System.Threading.Tasks; using System.Windows; public partial class MainWindow : Window { private Model model = new Model(); private Task pending = Task.FromResult(false); // Assume e carries a message received over the network. private void OnMessageReceived(object sender, EventArgs e) { this.pending = ApplyToModel(e); […]

如何使用Async / Await进行进度报告

假设我有一个文件列表,我必须使用c#project中的ftp相关类复制到Web服务器。 在这里我想使用Async / Awaitfunction,并且还希望同时显示多个文件上传的多个进度条。 每个进度条指示每个文件上载状态。 所以指导我如何做到这一点。 当我们与后台工作人员合作完成这种工作时,这很容易,因为后台工作人员有进度变更事件。 那么如何使用Async / Await来处理这种情况。 如果可能的话,用示例代码指导我。 谢谢

“等待Task.Yield()”及其替代品

如果我需要推迟代码执行,直到UI线程消息循环的未来迭代之后,我可以这样做: await Task.Factory.StartNew( () => { MessageBox.Show(“Hello!”); }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); 这类似于await Task.Yield(); MessageBox.Show(“Hello!”); await Task.Yield(); MessageBox.Show(“Hello!”); 除此之外,如果我愿意,我可以选择取消任务。 在使用默认同步上下文的情况下,我可以类似地使用await Task.Run继续池线程。 事实上,我比Task.Run更喜欢Task.Factory.StartNew和Task.Run ,因为它们都明确定义了延续代码的范围。 那么,在什么情况下await Task.Yield()实际上是有用的?

从Windows服务调用异步方法

我有一个用C#编写的Windows服务,可以定期激活后台作业。 通常,在任何给定时间,几十个重度I / O绑定任务(下载大文件等)并行运行。 该服务在一个相对繁忙的Web服务器上运行(目前是必需的),我认为在线程保护方面可以尽可能地使用异步API。 大部分工作都已完成。 所有作业现在完全异步(利用HttpClient等),主要作业循环(使用大量Task.Delay)也是如此。 剩下的就是弄清楚如何从服务的OnStart正确安全地启动主循环。 实际上,这是一个备受关注的呼叫异步同步困境。 以下是我到目前为止(非常简化)。 在Program.cs中: static void Main(string[] args) { TaskScheduler.UnobservedTaskException += (sender, e) => { // log & alert! e.SetObserved(); }; ServiceBase.Run(new MyService()); } 在MyService.cs中: protected override void OnStart(string[] args) { _scheduler.StartLoopAsync(); // fire and forget! will this get me into trouble? } 这是对我的调用StartLoopAsync 。 我不能简单地在返回的Task上使用Wait() ,因为OnStart需要相对快速地返回。 (作业循环需要在一个单独的线程上运行。)想到几个想法: […]

异步/等待作为协同程序的替代品

我使用C#迭代器作为协同程序的替代品,它一直很好用。 我想切换到async / await,因为我认为语法更清晰,它给了我类型安全。 在这篇(过时的)博客文章中,Jon Skeet展示了实现它的可能方法 。 我选择采用稍微不同的方式(通过实现我自己的SynchronizationContext并使用Task.Yield )。 这很好用。 然后我意识到会有问题; 目前协程不必完成运行。 它可以在任何产生的点上优雅地停止。 我们可能有这样的代码: private IEnumerator Sleep(int milliseconds) { Stopwatch timer = Stopwatch.StartNew(); do { yield return null; } while (timer.ElapsedMilliseconds < milliseconds); } private IEnumerator CoroutineMain() { try { // Do something that runs over several frames yield return Coroutine.Sleep(5000); } finally { Log("Coroutine […]

Task.WaitAll挂起了ASP.NET中的多个等待任务

下面是我遇到问题的代码的简化版本。 当我在控制台应用程序中运行它时,它按预期工作。 所有查询都是并行运行的, Task.WaitAll()在完成后返回。 但是,当此代码在Web应用程序中运行时,请求才会挂起。 当我附加一个调试器并中断所有时,它表明执行是在Task.WaitAll()上等待。 第一项任务已经完成,但其他任务都没有完成。 我无法弄清楚它在ASP.NET中运行时挂起的原因,但在控制台应用程序中运行良好。 public Foo[] DoWork(int[] values) { int count = values.Length; Task[] tasks = new Task[count]; for (int i = 0; i < count; i++) { tasks[i] = GetFooAsync(values[i]); } try { Task.WaitAll(tasks); } catch (AggregateException) { // Handle exceptions } return … } public async Task GetFooAsync(int value) […]