{"id":28043,"date":"2019-11-13T00:00:00","date_gmt":"2019-11-12T23:00:00","guid":{"rendered":"https:\/\/blexin.com\/?p=28043"},"modified":"2021-05-21T19:57:55","modified_gmt":"2021-05-21T17:57:55","slug":"async-e-await-in-applicazioni-reali","status":"publish","type":"post","link":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/","title":{"rendered":"Async e await in applicazioni reali"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" data-attachment-id=\"28044\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/attachment\/ebde7771-6bb2-4f29-9d23-c9e19c7af857\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&amp;ssl=1\" data-orig-size=\"1024,608\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ebde7771-6bb2-4f29-9d23-c9e19c7af857\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?resize=1024%2C608&#038;ssl=1\" alt=\"\" class=\"wp-image-28044\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png 1024w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857-980x582.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857-480x285.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Quando utilizziamo un metodo che impiega tempo per essere eseguito, come per la lettura di un file di grandi dimensioni o il download di risorse pesanti dalla rete, in una applicazione sincrona l\u2019intera applicazione smette di rispondere fino al completamento dell\u2019attivit\u00e0. In questi casi \u00e8 di grande aiuto la programmazione&nbsp;<strong>asincrona<\/strong>, che ci permette di parallelizzare l\u2019esecuzione di diversi task e, se necessario, attenderne il completamento.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Esistono diversi tipi di modelli per questo tipo di approccio alla programmazione: l\u2019<strong>APM<\/strong>&nbsp;(Asynchronous Programming Model), il modello asincrono basato su eventi (<strong>EAP<\/strong>) e il&nbsp;<strong>TAP<\/strong>, il modello asincrono basato su attivit\u00e0 (<strong>Task<\/strong>). Vediamo come in C# possiamo implementare il terzo, utilizzando le parole chiave<strong>&nbsp;async<\/strong>&nbsp;e&nbsp;<strong>await<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Uno dei principali problemi della scrittura di codice asincrono \u00e8 la manutenibilit\u00e0, dato che questo tipo di programmazione tende a complicare non poco il codice. Fortunatamente, C# 5 ha introdotto un approccio semplificato, in cui il compilatore esegue il lavoro difficile, che prima veniva svolto dallo sviluppatore, e l&#8217;applicazione mantiene una struttura logica simile al codice sincrono.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Facciamo un esempio. Supponiamo di avere un progetto .NET Core in cui dobbiamo gestire tre entit\u00e0: Area, Company e Resource.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class Area\n{\n\u00a0\u00a0\u00a0\u00a0public int Id { get; set; }\n\u00a0\n\u00a0\u00a0\u00a0\u00a0&#x5B;Required]\n\u00a0\u00a0\u00a0\u00a0&#x5B;StringLength(255)]\n\u00a0\u00a0\u00a0\u00a0public string Name { get; set; }\n}\n\u00a0\u00a0\npublic class Company\n{\n\u00a0\u00a0\u00a0\u00a0public int Id { get; set; }\n\u00a0\n\u00a0\u00a0\u00a0\u00a0&#x5B;Required]\n\u00a0\u00a0\u00a0\u00a0&#x5B;StringLength(255)]\n\u00a0\u00a0\u00a0\u00a0public string Name { get; set; }\n}\n\u00a0\npublic class Resource\n{\n\u00a0\u00a0\u00a0\u00a0public int Id { get; set; }\n\u00a0\n\u00a0\u00a0\u00a0\u00a0&#x5B;Required]\n\u00a0\u00a0\u00a0\u00a0&#x5B;StringLength(255)]\n\u00a0\u00a0\u00a0\u00a0public string Name { get; set; }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Supponiamo inoltre di dover salvare i valori di queste entit\u00e0 su un database, utilizzando Entity Framework Core. Il\u00a0<strong>DbContext<\/strong>\u00a0sar\u00e0 qualcosa del genere:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class AppDbContext : DbContext\n{\n\u00a0\u00a0\u00a0\u00a0public DbSet&lt;Area&gt; Areas { get; set; }\n\u00a0\u00a0\u00a0\u00a0public DbSet&lt;Company&gt; Companies { get; set; }\n\u00a0\u00a0\u00a0\u00a0public DbSet&lt;Resource&gt; Resources { get; set; }\n\u00a0\u00a0\u00a0\u00a0public AppDbContext(DbContextOptions&lt;AppDbContext&gt; options) : base(options)\u00a0 {}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0override protected void OnModelCreating(ModelBuilder modelBuilder)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0modelBuilder.Entity&lt;Area&gt; ().HasData(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 1, Name = &quot;Area1&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 2, Name = &quot;Area2&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 3, Name = &quot;Area3&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 4, Name = &quot;Area4&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 5, Name = &quot;Area5&quot;});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0modelBuilder.Entity&lt;Company&gt; ().HasData(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 1, Name = &quot;Company1&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 2, Name = &quot;Company2&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 3, Name = &quot;Company3&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 4, Name = &quot;Company4&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 5, Name = &quot;Company5&quot;});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0modelBuilder.Entity&lt;Resource&gt;().HasData(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 1, Name = &quot;Resource1&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 2, Name = &quot;Resource2&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 3, Name = &quot;Resource3&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 4, Name = &quot;Resource4&quot;},\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Area { Id = 5, Name = &quot;Resource5&quot;});\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Come potete vedere dal codice, abbiamo anche inserito qualche dato di esempio su cui lavorare. Supponiamo adesso di voler esporre con un&nbsp;<em>Controller Api<\/em>&nbsp;questi dati sia singolarmente per ogni entit\u00e0, che con un metodo che li aggreghi tutti, restituendoli con un\u2019unica chiamata.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Con un approccio sincrono, il\u00a0<em>Controller Api<\/em>\u00a0apparirebbe cos\u00ec:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;ApiController]\n&#x5B;Route(&quot;&#x5B;controller]&quot;)]\npublic class DataController : ControllerBase\n{\n\u00a0\u00a0\u00a0\u00a0private readonly AppDbContext db = null;\n\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public DataController(AppDbContext db)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.db = db;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0public IActionResult Get()\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var areas = this.GetAreas();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var companies = this.GetCompanies();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var resources = this.GetResources();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Ok(new { areas = areas, companies = companies, resources = resources });\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0&#x5B;Route(&quot;areas&quot;)]\n\u00a0\u00a0\u00a0\u00a0public Area&#x5B;] GetAreas() \n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return this.db.Areas.ToArray();\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0&#x5B;Route(&quot;companies&quot;)]\n\u00a0\u00a0\u00a0\u00a0public Company&#x5B;] GetCompanies() \n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return this.db.Companies.ToArray();\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0&#x5B;Route(&quot;resources&quot;)]\n\u00a0\u00a0\u00a0\u00a0public Resource&#x5B;] GetResources() \n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return this.db.Resources.ToArray();\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Il metodo Get() chiamer\u00e0 al suo interno i tre metodi che restituiscono i singoli risultati, attendendo che sia completata l\u2019esecuzione di ognuno prima di passare al successivo. I tre metodi non sono legati tra loro, non ho bisogno di attendere l\u2019esecuzione di uno di loro per poterne invocare un altro. Posso quindi creare tre Task indipendenti per parallelizzare l\u2019esecuzione.<br>Un primo approccio pu\u00f2 essere basato sul metodo\u00a0<strong>Run<\/strong>\u00a0della classe\u00a0<strong>Task<\/strong>, che accoda il lavoro specificato da eseguire nel\u00a0<em>pool<\/em>\u00a0di\u00a0<em>thread<\/em>\u00a0e restituisce un oggetto\u00a0<strong>Task<\/strong>\u00a0che rappresenta tale lavoro. In questo modo, i metodi vengono eseguiti contemporaneamente su differenti thread del pool:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic IActionResult Get()\n{\n\u00a0\u00a0\u00a0\u00a0var areas = Task.Run(() = &gt; this.GetAreas());\n\u00a0\u00a0\u00a0\u00a0var companies = Task.Run(() = &gt; this.GetCompanies());\n\u00a0\u00a0\u00a0\u00a0var resources = Task.Run(() = &gt; this.GetResources());\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \n\u00a0\u00a0\u00a0\u00a0Task.WhenAll(areas, companies, resources);\n\u00a0\u00a0\u00a0\u00a0return Ok(new { areas = areas.Result, companies = companies.Result, resources = resources.Result });\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">La propriet\u00e0&nbsp;<strong>Result<\/strong>&nbsp;di&nbsp;<strong>Task<\/strong>&nbsp;conterr\u00e0 il risultato dell\u2019elaborazione. Il metodo&nbsp;<em>WhenAll<\/em>&nbsp;permette di sospendere l\u2019esecuzione del thread corrente fino al completamento di tutti i Task.<br>Eseguendo il codice per\u00f2, notiamo una cosa interessante: la chiamata si interrompe lanciando l\u2019eccezione seguente:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;<em>AggregateException: One or more errors occurred. (A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see<\/em>&nbsp;<a href=\"https:\/\/go.microsoft.com\/fwlink\/?linkid=2097913\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/go.microsoft.com\/fwlink\/?linkid=2097913&nbsp;<\/a>)&#8221;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Questo errore ci dice da una parte che i metodi vengono effettivamente eseguiti contemporaneamente su thread diversi, ma siccome utilizzano la stessa istanza del\u00a0<strong>DbContext<\/strong>\u00a0per la connessione al db, viene sollevata un\u2019eccezione.<br>La classe\u00a0<strong>DbContext<\/strong>\u00a0non pu\u00f2 assicurare un funzionamento<em>\u00a0threadsafe<\/em>, problema che possiamo aggirare facilmente non facendoci creare pi\u00f9 una singola istanza del\u00a0<strong>DbContext<\/strong>\u00a0dal motore di\u00a0<em>dependency injection<\/em>\u00a0di .NET Core, ma creando noi una istanza separata per ogni metodo. A titolo di esempio, vediamo come cambierebbe il metodo GetAreas():<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class DataController : ControllerBase\n{\n\u00a0\u00a0\u00a0\u00a0private readonly DbContextOptionsBuilder &lt;AppDbContext&gt; optionsBuilder = null;\n\u00a0\u00a0\u00a0\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public DataController(IConfiguration configuration)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.optionsBuilder = new DbContextOptionsBuilder &lt;AppDbContext&gt; ()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.UseSqlite(configuration.GetConnectionString(&quot;DefaultConnection&quot;));\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0&#x5B;Route(&quot;areas&quot;)]\n\u00a0\u00a0\u00a0\u00a0public Area&#x5B;] GetAreas() \n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0using(var db = new AppDbContext(this.optionsBuilder.Options))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return db.Areas.ToArray();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Ok, ora funziona. In realt\u00e0 per\u00f2,\u00a0<em>Entity Framework Core<\/em>\u00a0fornisce dei metodi per fare chiamate asincrone con lo stesso\u00a0<strong>DbContext<\/strong>, come ad esempio il metodo\u00a0<em>ToArrayAsync<\/em>, che crea un array da un\u00a0<em>IQueryable&lt;T><\/em>\u00a0enumerandolo in modo asincrono. Questo metodo restituisce un\u00a0<strong>Task&lt;TSource[]><\/strong>, un&#8217;attivit\u00e0 che rappresenta l&#8217;operazione asincrona, in questo modo non abbiamo pi\u00f9 bisogno di usare\u00a0<em>Task.Run()<\/em>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic IActionResult Get()\n{\n\u00a0\u00a0\u00a0\u00a0var areas = this.GetAreas();\n\u00a0\u00a0\u00a0\u00a0var companies = this.GetCompanies();\n\u00a0\u00a0\u00a0\u00a0var resources = this.GetResources();\n\u00a0\u00a0\u00a0\u00a0Task.WhenAll(areas, companies, resources);\n\u00a0\u00a0\u00a0\u00a0return Ok(new { areas = areas.Result, companies = companies.Result, resources = resources.Result });\n}\n\u00a0\u00a0\n&#x5B;Route(&quot;areas&quot;)]\npublic Task&lt;Area&#x5B;]&gt; GetAreas() \n{\n\u00a0\u00a0\u00a0\u00a0return db.Areas.ToArrayAsync();\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Tuttavia, Microsoft non assicura che questi metodi asincroni funzionino in ogni circostanza, perch\u00e9 comunque il DbContext non \u00e8 progettato per essere threadsafe. Per maggiori info potete consultare questo link:&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/ef\/core\/querying\/async\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/docs.microsoft.com\/en-us\/ef\/core\/querying\/async<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quindi, la best practice quando lavorate con Entity Framework Core \u00e8 di avere un DbContext per ogni operazione asincrona o attendere che ognuna di essa sia finita prima di lanciarne un\u2019altra.<br>Tutto bene finch\u00e9 quello che dobbiamo fare \u00e8 una chiamata asincrona e restituirne il risultato. Ma se volessimo invece fare delle operazioni con il risultato prima di restituirlo? Ad esempio, se volessimo aggiungere un elemento alla lista? Dobbiamo attendere i risultati, aggiungere l\u2019elemento e restituire la lista modificata:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;Route(&quot;companies&quot;)]\npublic Task&lt;Company&#x5B;]&gt; GetCompanies() \n{\n\u00a0\u00a0\u00a0\u00a0using (var db = new AppDbContext(this.optionsBuilder.Options))\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var data = this.db.Companies.ToListAsync().Result;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data.Insert(0, new Company() { Id = 0, Name = &quot;-&quot;});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return data.ToArray();\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Peccato che questo codice non compili, perch\u00e9 il data.ToArray() restituisce un array, non un Task. Infatti, qui ci servono 3 thread: il chiamante principale (Get()), la query sul database (this.db.Companies.ToListAsync()) e un thread che aggiunge il valore alla lista. Come facciamo? Abbiamo tre modi, vediamoli tutti e tre con i nostri tre metodi singoli. Il primo, che abbiamo gi\u00e0 visto, pu\u00f2 utilizzare il metodo Task.Run():<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;Route(&quot;companies&quot;)]\npublic Task&lt;Company&#x5B;]&gt; GetCompanies()\n{\n\u00a0\u00a0\u00a0\u00a0\u00a0return Task.Run(() =&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0using (var db = new AppDbContext(this.optionsBuilder.Options))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var data = db.Companies.ToList();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data.Insert(0, new Company() { Id = 0, Name = &quot;-&quot; });\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return data.ToArray();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0});\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In alternativa possiamo utilizzare il metodo\u00a0<strong>ContinueWith()<\/strong>\u00a0che si applica ai Task e in cui possiamo specificare un nuovo Task da eseguire appena quello precedente \u00e8 concluso:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;Route(&quot;resources&quot;)]\npublic Task &lt;Resource&#x5B;]&gt; GetResources()\n{\n\u00a0\u00a0\u00a0\u00a0\u00a0using (var db = new AppDbContext(this.optionsBuilder.Options))\n\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return db.Resources.ToListAsync()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.ContinueWith(dataTask = &gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var data = dataTask.Result;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dataTask.Result.Insert(0, new Resource() { Id = 0, Name = &quot;-&quot; });\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return data.ToArray();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Oppure, possiamo far fare il lavoro sporco al compilatore e sfruttare le keyword\u00a0<strong>async<\/strong>\u00a0e\u00a0<strong>await<\/strong>, che creeranno per noi il Task:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;Route(&quot;areas&quot;)]\npublic async Task &lt;Area&#x5B;]&gt; GetAreas()\n{\n\u00a0\u00a0\u00a0\u00a0\u00a0using (var db = new AppDbContext(this.optionsBuilder.Options))\n\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var data = await db.Areas.ToListAsync();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0data.Insert(0, new Area() { Id = 0, Name = &quot;-&quot; });\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return data.ToArray();\n\u00a0\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Come potete notare in questo ultimo metodo, il codice \u00e8 molto pi\u00f9 semplice e ci nasconde la creazione del Task, permettendoci di dare una return sincrona. Immaginatevi uno scenario in cui le chiamate sono pi\u00f9 di una e come questo approccio renda tutto pi\u00f9 lineare.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Come effetto collaterale del nostro refactoring, abbiamo adesso un metodo GetAreas() che \u00e8 diventato una&nbsp;<strong>action asincrona<\/strong>, il che significa che quando arriveranno diverse richieste a questa API, il thread del pool allocato per la richiesta sar\u00e0 rilasciato per dare disponibilit\u00e0 ad altre richieste finch\u00e9 il DbContext non avr\u00e0 terminato il fetch dei dati.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Spero di avervi incuriosito abbastanza da approfondire l\u2019argomento. L\u2019utilizzo di async e await \u00e8 molto comodo in tanti scenari e, oltre a rendere il codice pi\u00f9 pulito e lineare, pu\u00f2 portare ad un incremento delle performance generali dell\u2019applicazione.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Trovate tutto il codice qui:&nbsp;<a href=\"https:\/\/github.com\/fvastarella\/Programmazione-asincrona-con-async-await\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/fvastarella\/Programmazione-asincrona-con-async-await<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Alla prossima!<\/p>\n\n\n\n\n","protected":false},"excerpt":{"rendered":"<p>Vediamo come le keyword async e await possono semplificare la programmazione multithreading in C# in casi reali<\/p>\n","protected":false},"author":196716244,"featured_media":28044,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"off","_et_pb_old_content":"","_et_gb_content_width":"","_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","inline_featured_image":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"{title}\n\n{excerpt}\n\n{url}","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false},"categories":[688637374],"tags":[688637541,688637382],"class_list":["post-28043","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-dotnetcore","tag-c"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Async e await in applicazioni reali - Blexin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Async e await in applicazioni reali - Blexin\" \/>\n<meta property=\"og:description\" content=\"Vediamo come le keyword async e await possono semplificare la programmazione multithreading in C# in casi reali\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/\" \/>\n<meta property=\"og:site_name\" content=\"Blexin\" \/>\n<meta property=\"article:published_time\" content=\"2019-11-12T23:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-05-21T17:57:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i1.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"608\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Francesco Vastarella\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Francesco Vastarella\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/\"},\"author\":{\"name\":\"Francesco Vastarella\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/388dae0ca9df603c88b5e41e29cf2d4d\"},\"headline\":\"Async e await in applicazioni reali\",\"datePublished\":\"2019-11-12T23:00:00+00:00\",\"dateModified\":\"2021-05-21T17:57:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/\"},\"wordCount\":1024,\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1\",\"keywords\":[\".NetCore\",\"C#\"],\"articleSection\":[\"Blog\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/\",\"name\":\"Async e await in applicazioni reali - Blexin\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1\",\"datePublished\":\"2019-11-12T23:00:00+00:00\",\"dateModified\":\"2021-05-21T17:57:55+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/388dae0ca9df603c88b5e41e29cf2d4d\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1\",\"width\":1024,\"height\":608},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/async-e-await-in-applicazioni-reali\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blexin.com\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Async e await in applicazioni reali\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/\",\"name\":\"Blexin\",\"description\":\"Con noi \u00e8 semplice\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blexin.com\\\/it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/388dae0ca9df603c88b5e41e29cf2d4d\",\"name\":\"Francesco Vastarella\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3b8deedae8f35372d5fba49f918006fb0a58a2943aff6ae52d3ff188e0c441bb?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3b8deedae8f35372d5fba49f918006fb0a58a2943aff6ae52d3ff188e0c441bb?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3b8deedae8f35372d5fba49f918006fb0a58a2943aff6ae52d3ff188e0c441bb?s=96&d=identicon&r=g\",\"caption\":\"Francesco Vastarella\"},\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/author\\\/francesco-vastarellablexin-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Async e await in applicazioni reali - Blexin","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/","og_locale":"it_IT","og_type":"article","og_title":"Async e await in applicazioni reali - Blexin","og_description":"Vediamo come le keyword async e await possono semplificare la programmazione multithreading in C# in casi reali","og_url":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/","og_site_name":"Blexin","article_published_time":"2019-11-12T23:00:00+00:00","article_modified_time":"2021-05-21T17:57:55+00:00","og_image":[{"width":1024,"height":608,"url":"https:\/\/i1.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1","type":"image\/png"}],"author":"Francesco Vastarella","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"Francesco Vastarella","Tempo di lettura stimato":"8 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/#article","isPartOf":{"@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/"},"author":{"name":"Francesco Vastarella","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/388dae0ca9df603c88b5e41e29cf2d4d"},"headline":"Async e await in applicazioni reali","datePublished":"2019-11-12T23:00:00+00:00","dateModified":"2021-05-21T17:57:55+00:00","mainEntityOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/"},"wordCount":1024,"image":{"@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1","keywords":[".NetCore","C#"],"articleSection":["Blog"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/","url":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/","name":"Async e await in applicazioni reali - Blexin","isPartOf":{"@id":"https:\/\/blexin.com\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/#primaryimage"},"image":{"@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1","datePublished":"2019-11-12T23:00:00+00:00","dateModified":"2021-05-21T17:57:55+00:00","author":{"@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/388dae0ca9df603c88b5e41e29cf2d4d"},"breadcrumb":{"@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/#primaryimage","url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1","contentUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1","width":1024,"height":608},{"@type":"BreadcrumbList","@id":"https:\/\/blexin.com\/it\/blog\/async-e-await-in-applicazioni-reali\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blexin.com\/it\/"},{"@type":"ListItem","position":2,"name":"Async e await in applicazioni reali"}]},{"@type":"WebSite","@id":"https:\/\/blexin.com\/it\/#website","url":"https:\/\/blexin.com\/it\/","name":"Blexin","description":"Con noi \u00e8 semplice","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blexin.com\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Person","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/388dae0ca9df603c88b5e41e29cf2d4d","name":"Francesco Vastarella","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/3b8deedae8f35372d5fba49f918006fb0a58a2943aff6ae52d3ff188e0c441bb?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/3b8deedae8f35372d5fba49f918006fb0a58a2943aff6ae52d3ff188e0c441bb?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3b8deedae8f35372d5fba49f918006fb0a58a2943aff6ae52d3ff188e0c441bb?s=96&d=identicon&r=g","caption":"Francesco Vastarella"},"url":"https:\/\/blexin.com\/it\/author\/francesco-vastarellablexin-com\/"}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ebde7771-6bb2-4f29-9d23-c9e19c7af857.png?fit=1024%2C608&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/pcyUBx-7ij","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28043","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/users\/196716244"}],"replies":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/comments?post=28043"}],"version-history":[{"count":4,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28043\/revisions"}],"predecessor-version":[{"id":28050,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28043\/revisions\/28050"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media\/28044"}],"wp:attachment":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media?parent=28043"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/categories?post=28043"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/tags?post=28043"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}