{"id":2913,"date":"2009-04-01T03:32:00","date_gmt":"2009-04-01T03:32:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2009\/04\/01\/using-negative-sleeps-to-improve-responsiveness-in-vb-web-apps\/"},"modified":"2024-07-05T13:30:56","modified_gmt":"2024-07-05T20:30:56","slug":"using-negative-sleeps-to-improve-responsiveness-in-vb-web-apps","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/using-negative-sleeps-to-improve-responsiveness-in-vb-web-apps\/","title":{"rendered":"Using &#034;negative sleeps&#034; to improve responsiveness in VB web apps"},"content":{"rendered":"<p>[NOTE:&nbsp;please also read the <a href=\"http:\/\/blogs.msdn.com\/vbteam\/archive\/2009\/04\/06\/negative-delays-not-in-vb-lucian-wischik.aspx\">followup<\/a> to this article]&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>.NET 4.0 will introduce many new threading and concurrency classes &#8212; SpinLock, Parallel Linq, and ConcurrentDictionary to name but a few.<\/p>\n<p>The new feature that excites me the most is the ability to pass a negative&nbsp;argument to&nbsp;<strong>Thread.Sleep<\/strong>. This article describes how you can use it to speed up a program by compensating for internet latency.<\/p>\n<p>Let&#8217;s start with&nbsp;a simple VB program which retrieves an RSS feed and produces from it a new feed with only those items from a particular date of the year:<\/p>\n<p class=\"MsoNormal\"><span>Option<\/span><span> <span>Strict<\/span> <span>On<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span>Imports<\/span><span> System.Net<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Imports<\/span><span> System.IO<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>Module<\/span><span> Module1<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Sub<\/span> Main()<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> xml = Fetch(<span>New<\/span> Uri(<span>&#8220;http:\/\/blogs.msdn.com\/vbteam\/rss.xml&#8221;<\/span>))<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> items = <span>From<\/span> item <span>In<\/span> xml.<span>&lt;<\/span>channel<span>&gt;<\/span>.<span>&lt;<\/span>item<span>&gt;<\/span> <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Select<\/span> title = item.<span>&lt;<\/span>title<span>&gt;<\/span>.Value,<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>url = item.<span>&lt;<\/span>link<span>&gt;<\/span>.Value,<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>time = DateTime.Parse(item.<span>&lt;<\/span>pubDate<span>&gt;<\/span>.Value)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Where<\/span> time.Month = 4&nbsp;<span>AndAlso<\/span> time.Day = 1<\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> rss = <span>&lt;<\/span><span>rss<\/span> <span>version<\/span><span>=<\/span><span>&#8220;<\/span><span>2.0<\/span><span>&#8220;<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>channel<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>title<\/span><span>&gt;<\/span><span>Refeed<\/span><span>&lt;\/<\/span><span>title<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>description<\/span><span>&gt;<\/span><span>The last week of the feed<\/span><span>&lt;\/<\/span><span>description<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>language<\/span><span>&gt;<\/span><span>en<\/span><span>&lt;\/<\/span><span>language<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>ttl<\/span><span>&gt;<\/span><span>120<\/span><span>&lt;\/<\/span><span>ttl<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>pubDate<\/span><span>&gt;<\/span><span>&lt;%=<\/span> Now.ToString(<span>&#8220;r&#8221;<\/span>) <span>%&gt;<\/span><span>&lt;\/<\/span><span>pubDate<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;%=<\/span> <span>From<\/span> item <span>In<\/span> items <span>Select<\/span> <\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>item<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>title<\/span><span>&gt;<\/span><span>&lt;%=<\/span> item.title <span>%&gt;<\/span><span>&lt;\/<\/span><span>title<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;<\/span><span>pubDate<\/span><span>&gt;<\/span><span>&lt;%=<\/span> item.time.ToString(<span>&#8220;r&#8221;<\/span>) <span>%&gt;<\/span><span>&lt;\/<\/span><span>pubDate<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/span><span>&lt;<\/span><span>link<\/span><span>&gt;<\/span><span>&lt;%=<\/span> item.url <span>%&gt;<\/span><span>&lt;\/<\/span><span>link<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;\/<\/span><span>item<\/span><span>&gt;<\/span> <span>%&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;\/<\/span><span>channel<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&lt;\/<\/span><span>rss<\/span><span>&gt;<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Console.WriteLine(rss)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Sub<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Function<\/span> Fetch(<span>ByVal<\/span> url <span>As<\/span> Uri) <span>As<\/span> XElement<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> x = WebRequest.Create(url)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Using<\/span> r = x.GetResponse, rs <span>As<\/span> <span>New<\/span> StreamReader(r.GetResponseStream)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Return<\/span> XElement.Parse(rs.ReadToEnd)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Using<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>End<\/span> <span>Function<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span>End<\/span><span> <span>Module<\/p>\n<p><\/span><\/span><\/p>\n<p>How to optimize this? The important rule of thumb is that &#8220;everything done over the internet is much slower than anything done locally&#8221;. In this case&nbsp;the bottleneck is the call&nbsp;to Fetch \/ WebRequest.GetResponse, so it&#8217;s this that we have to optimize.<\/p>\n<p>The key idea is to use the new &#8220;negative argument&#8221; feature of Threading.Thread.Sleep:<\/p>\n<p><span>Public<\/span><span> <\/span><span>Shared<\/span><span> <\/span><span>Sub<\/span><span> Sleep (millisecondsTimeout <\/span><span>As<\/span><span> <\/span><span>Integer<\/span><span>)<\/span><\/p>\n<p>The argument says how long must elapse before the next statement executes. Up to .NET3.5, the millisecondsTimeout had to be positive, or &#8220;-1&#8221; to indicate infinity, and if you passed any other number then it threw an ArgumentOutOfRange exception.<\/p>\n<p>&nbsp;<\/p>\n<p><strong><em>Negative sleeps<\/em><\/strong><\/p>\n<p>Starting with .NET4.0, you can pass any negative argument to Thread.Sleep. As you&#8217;d expect,&nbsp;a negative argument&nbsp;indicates that the next statement should be executed earlier. Exception: for backwards compatibility, Thread.Sleep(-1) still has the special meaning &#8220;Infinite Sleep&#8221;. If you really want to sleep for -1ms rather than infinity you should use Thread.SleepEx(-1), which doesn&#8217;t have the special interpretation for -1.<\/p>\n<p>And so we&#8217;ll rewrite the function &#8220;Fetch&#8221; to use negative sleeps. The&nbsp;logic&nbsp;is subtle, so I give a few lines of code and then explain what they&#8217;re doing:<\/p>\n<p class=\"MsoNormal\"><span><span>Function<\/span> FetchFaster(<span>ByVal<\/span> url <span>As<\/span> Uri) <span>As<\/span> XElement<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Static<\/span> Delays <span>As<\/span> <span>New<\/span> LinkedList(<span>Of<\/span> <span>Integer<\/span>) <span>&#8216; Typical latencies (ms)<\/span><\/span><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p>As shown&nbsp;above, we&#8217;re going to keep a record of typical past latencies for the&nbsp;web request&nbsp;in the &#8220;Delays&#8221; variable. That lets us calculate the average latency of web requests given our internet connection.<\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; Do a negative sleep before sending the request, so that the<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; response will be ready at approximately the time it&#8217;s needed<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> expectedLatency = <span>If<\/span>(Delays.Count = 0, 0, <span>CInt<\/span>(Delays.Average()))<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span>Thread.Sleep(-expectedLatency)<\/span><\/p>\n<p>In the code above, Thread.Sleep(-expectedLatency) passes a <em>negative<\/em> argument to Thread.Sleep before executing the web request. Thus, if typical latency is 140ms, all we&#8217;re doing is issuing our web request 140ms earlier than would otherwise have been the case.<\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> startTime = Now<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> x = WebRequest.Create(url)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp; <\/span><span>Using<\/span> r = x.GetResponse, rs <span>As<\/span> <span>New<\/span> StreamReader(r.GetResponseStream)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&#8216; Calculate the latency on this call, and add it into the &#8220;Delays&#8221; log<\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>Dim<\/span> actualLatency = <span>CInt<\/span>((Now &#8211; startTime).TotalMilliseconds)<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>If<\/span> (Delays.Count &gt;= 10) <span>Then<\/span> Delays.RemoveFirst()<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[NOTE:&nbsp;please also read the followup to this article]&nbsp; &nbsp; .NET 4.0 will introduce many new threading and concurrency classes &#8212; SpinLock, Parallel Linq, and ConcurrentDictionary to name but a few. The new feature that excites me the most is the ability to pass a negative&nbsp;argument to&nbsp;Thread.Sleep. This article describes how you can use it to [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[192,195],"tags":[99],"class_list":["post-2913","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-visual-basic","tag-lucian-wischik"],"acf":[],"blog_post_summary":"<p>[NOTE:&nbsp;please also read the followup to this article]&nbsp; &nbsp; .NET 4.0 will introduce many new threading and concurrency classes &#8212; SpinLock, Parallel Linq, and ConcurrentDictionary to name but a few. The new feature that excites me the most is the ability to pass a negative&nbsp;argument to&nbsp;Thread.Sleep. This article describes how you can use it to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/2913","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=2913"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/2913\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=2913"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=2913"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=2913"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}