在我们的应用程序中,我们使用 async 调用。我们需要等待这些调用,以便我们使用等待。但是我们注意到应用程序在HttpClient.SendAsync
等待的其他地方继续应用程序。我们使用以下代码复制它: -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace AsyncExperiment
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("1");
var adapter = new Adapter();
Console.WriteLine("2");
var result = Task.Factory.StartNew(() => adapter.Start()).Result;
Console.WriteLine("21");
Console.ReadKey();
}
}
public class Adapter
{
public async Task<string> Start()
{
Console.WriteLine("3");
return await CollectionAccessor.ExecuteWithinScope(async collection => {
Console.WriteLine("8");
var adapter = new AsyncSearchAdapter();
Console.WriteLine("9");
var result = await adapter.GetSearchAsync();
Console.WriteLine("19");
Console.WriteLine(result);
Console.WriteLine("20");
return "";
});
}
}
public class Client
{
public async Task<string> Get()
{
Console.WriteLine("12");
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "https://22ad5e1e-688d-4ba4-9287-6bb4a351fd05.mock.pstmn.io/test");
Console.WriteLine("13");
HttpClient httpClient = new HttpClient();
Console.WriteLine("14");
HttpResponseMessage response = await httpClient.SendAsync(requestMessage);
Console.WriteLine("15");
if(response.IsSuccessStatusCode){
Console.WriteLine("16a");
return await response.Content.ReadAsStringAsync();
}
Console.WriteLine("16b");
return null;
}
}
public class AsyncSearchAdapter
{
public async Task<string> GetSearchAsync()
{
Console.WriteLine("10");
var client = new Client();
Console.WriteLine("11");
var response = await client.Get();
Console.WriteLine("17");
if(response.Equals("{'test', 'test'}")){
Console.WriteLine("18a");
return response;
}
Console.WriteLine("18b");
return response;
}
}
public static class CollectionAccessor
{
public static TReturn ExecuteWithinScope<TReturn>(Func<ICatalogCollection, TReturn> func)
{
Console.WriteLine("4");
if(func == null) throw new ArgumentNullException("func");
Console.WriteLine("5");
using(var catalogCollection = Resolver())
{
Console.WriteLine("7");
return func(catalogCollection);
}
}
public static ICatalogCollection Resolver()
{
Console.WriteLine("6");
return new CatalogCollection();
}
}
public interface ICatalogCollection: IDisposable
{
string notImportant { get;}
}
public class CatalogCollection : ICatalogCollection, IDisposable
{
public string notImportant { get;}
public CatalogCollection(){
notImportant = "test";
}
public void Dispose()
{
throw new NotImplementedException();
}
}
}
我们希望日志的顺序是
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21
但是我们得到了这样的订单:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,21,15,16,17,18,19,20
有人可以向我解释为什么会按此顺序发生这种情况。以及如何按预期顺序获得它?
感谢!!!
答案 0 :(得分:4)
您正在运行异步功能(/deep/ .k-window-titlebar {
background-color: blue;
}
)而不是等待它。尝试改变
adapter.Start()
到
var result = Task.Factory.StartNew(() => adapter.Start()).Result;
或
var result = adapter.Start().Result;
我猜你在这里也遇到同样的问题
var result = Task.Factory.StartNew(() => adapter.Start().Result).Result;
确保await CollectionAccessor.ExecuteWithinScope(async collection => {...})
将处理等待传递的函数。像
CollectionAccessor.ExecuteWithinScope
或至少归还
async Task CollectionAccessor.ExecuteWithinScope(Func <ICollection, Task> action)
{
...
await (action(collection));
...
}
<强> UPD 强>
就在这里
async Task CollectionAccessor.ExecuteWithinScope(Func <ICollection, Task> action)
{
...
return (action(collection));
}
您正在创建尚未完成的任务,并且您返回它并在任务完成之前处理集合。 我想你需要等待任务完成,并且只有在它返回之后。喜欢
public static TReturn ExecuteWithinScope<TReturn>(Func<ICatalogCollection, TReturn> func)
{
Console.WriteLine("4");
if (func == null) throw new ArgumentNullException("func");
Console.WriteLine("5");
using (var catalogCollection = Resolver())
{
Console.WriteLine("7");
return func(catalogCollection); // <<<<<<<HERE
}
}
OR 您需要在任务中部署集合,例如
public static async Task<TReturn> ExecuteWithinScope<TReturn>(Func<ICatalogCollection, Task<TReturn>> func)
{
Console.WriteLine("4");
if (func == null) throw new ArgumentNullException("func");
Console.WriteLine("5");
using (var catalogCollection = Resolver())
{
Console.WriteLine("7");
return await func(catalogCollection); // waiting task for completition
}
}
然后
public static TReturn ExecuteWithinScope<TReturn>(Func<ICatalogCollection, TReturn> func)
{
Console.WriteLine("4");
if (func == null) throw new ArgumentNullException("func");
Console.WriteLine("5");
//using (var catalogCollection = Resolver()) // not in using!
{
var catalogCollection = Resolver();
Console.WriteLine("7");
return func(catalogCollection);
}
}
从我的观点第一种方法( return await CollectionAccessor.ExecuteWithinScope(async collection =>
{
Console.WriteLine("8");
var adapter = new AsyncSearchAdapter();
Console.WriteLine("9");
var result = await adapter.GetSearchAsync();
Console.WriteLine("19");
Console.WriteLine(result);
Console.WriteLine("20");
collection.Dispose(); //// Disposing!
return "";
});
) - 最好的方法