我正在使用Microsoft Web API 2.2客户端从API端点请求数据。在我得到数据后,我运行了x个DoSomeWork。我想确保在运行DoSomeWork函数之前先加载数据。
根据下面的代码,我期望得到以下输出。
"正在启动GetSomething"完成GetSomething"开始工作#1"开始工作#2"
但我得到了追随者"正在启动GetSomething"开始工作#1"完成GetSomething"开始工作#2"
static void Main()
{
try
{
Task getSomethingTask = Task.Factory.StartNew(()=>GetSomething());
getSomethingTask.Wait();
Task[] tasks = new Task[2] {
Task.Facotry.StartNew(()=>DoSomeWork(1)),
Task.Facotry.StartNew(()=>DoSomeWork(2))
};
Task.WaitAll(tasks);
}
catch(Exception ex)
{
throw ex;
}
}
static async Task GetSomething()
{
Console.WriteLine("Starting GetSomething");
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(SOME_URL);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("api/v1/somethings");
somethingList = await response.Content.ReadAsAsync<SomeObject>();
}
catch (Exception)
{
throw;
}
Console.WriteLine("Done with GetSomething");
}
static async Task DoSomeWork(int workNumber)
{
Console.Writeline("Start work#" + workNumber);
}
进行异步编程(即i/O绑定)时,需要避免StartNew
、Wait
和WaitAll
。相反,几乎所有逻辑都使用async
和await
。
由于这是一个控制台应用程序,您确实需要一个Wait
,这样主线程就不会退出。这应该是你整个应用程序中唯一的Wait
:
static void Main()
{
MainAsync().Wait();
}
static async Task MainAsync()
{
await GetSomethingAsync();
await Task.WhenAll(DoSomeWorkAsync(1), DoSomeWorkAsync(2));
}
static async Task GetSomethingAsync()
{
Console.WriteLine("Starting GetSomething");
HttpClient client = new HttpClient();
...
HttpResponseMessage response = await client.GetAsync("api/v1/somethings");
somethingList = await response.Content.ReadAsAsync<SomeObject>();
Console.WriteLine("Done with GetSomething");
}
static async Task DoSomeWorkAsync(int workNumber)
{
Console.Writeline("Start work#" + workNumber);
}
你可能会发现我的async
简介很有帮助。
我相信getSomethingTask
会立即结束,因为您不是await
或GetSomething()
。
试试这个:
Task getSomethingTask = Task.Factory.StartNew(async () => await GetSomething());
或者简单地说:
GetSomething().Wait();
尽管我不认为通过创建一个新线程并立即在主线程上等待结果真的会有什么收获。
当您从线程调用await
时,您将控制权交还给其父线程。
在这种情况下,这是你的冒犯行:
HttpResponseMessage response = await client.GetAsync("api/v1/somethings");
一旦这样做,GetSomething
线程就会将控制权交还给Main()
线程,这就是为什么您会看到DoSomeWork
任务正在执行。
如果在GetSomething
中去掉那些await
调用,代之以同步调用,您将获得所需的行为。
有关更多信息,请参阅此处的Microsoft异步编程指南(特别是步骤#6,其中谈到了await
):http://msdn.microsoft.com/async