触发 HttpClient 的更简单方法(可能没有任务)?
Simplier way to trigger HttpClient (maybe without Task)?
我正在开发将使用我自己的 REST endpoints
的应用程序(我有自己的 WebApi
项目)。现在我尝试构建可在该端点上运行的应用程序。
基于 this MSDN 教程,我做了这样的事情:
为了测试,我制作了 Console Core 应用程序。主要 class 看起来像这样:
class Program
{
public static HttpDataService http = new HttpDataService("authorization token here");
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
RunAsync().GetAwaiter().GetResult();
}
static async Task RunAsync()
{
var data = await http.Get("Default");
}
}
我的主要 Http
class 看起来像这样:
public class HttpDataService
{
public HttpDataService(string token)
{
this.HttpClient = new HttpClient();
this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
private HttpClient HttpClient { get; set; }
public async Task<object> Get(string controller)
{
object data;
HttpResponseMessage response = await this.HttpClient.GetAsync(UrlService.BuildEndpoint(controller));
if (response.IsSuccessStatusCode)
{
data = await response.Content.ReadAsAsync<object>();
return data;
}
else
{
throw new Exception(); //todo
}
}
}
我不喜欢额外的步骤,我需要为 运行 任务执行方法(Main 方法中的 RunAsync.GetAwaiter...
)。
有没有更简单的方法来使用我自己的端点?也许其他一些不需要额外方法的库(这样,static Async Task Run
)?有没有办法像这样触发方法:
http.Get("Projects");
没有我之前写的RunAsync()
方法?
PS。该控制台应用程序工作正常(我从我的 WebApi 项目的 Default
控制器获取值)
编辑
这样看起来更人性化:
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Task get = http.Get("default");
RunAsync(get).GetAwaiter().GetResult();
}
static async Task RunAsync(Task endpoint)
{
await endpoint;
}
但是如何从 endpoint
中获取?
您的代码有 2 个问题。第一个是你的 RunAsync
方法 returns Task
而你的方法 HttpDataService.Get
return Task<object>
。要从端点获得结果,RunAsync
应该 return Task<object>
。当你等待这个任务时,你会得到一个包含你结果的对象。
对于.GetAwaiter().GetResult()
,有2个选项。首先,您可以创建一个 static async Task MainAsync
并在其中 运行 所有代码并通过调用 MainAsync().GetAwaiter().GetResult()
从非同步 Main
方法调用此方法。在 C# 7.1 之前,这是要走的路。
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
static async Task MainAsync(string[] args)
{
// Run your async code here
}
如果您使用 C# 7.1,您可以使您的 Main
-方法异步 (static async Task Main(string[] args)
),然后您可以从那里直接调用您的异步代码。
static async Task Main(string[] args)
{
// Run your async code here
}
你可以使用助手class
public static class AsyncHelper
{
private static readonly TaskFactory _taskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
=> _taskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
public static void RunSync(Func<Task> func)
=> _taskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
允许你这样做:
static async Task RunAsync(Task endpoint) {
AsyncHelper.RunSync(() => endpoint());
}
PS。看看这里 Ms AsyncHelper and here C# Async Tips & Tricks
你应该Main
异步。
注意:仅适用于现代 c#
static async Task Main(string[] args)
{
var result = await http.Get("default");
}
我正在开发将使用我自己的 REST endpoints
的应用程序(我有自己的 WebApi
项目)。现在我尝试构建可在该端点上运行的应用程序。
基于 this MSDN 教程,我做了这样的事情:
为了测试,我制作了 Console Core 应用程序。主要 class 看起来像这样:
class Program
{
public static HttpDataService http = new HttpDataService("authorization token here");
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
RunAsync().GetAwaiter().GetResult();
}
static async Task RunAsync()
{
var data = await http.Get("Default");
}
}
我的主要 Http
class 看起来像这样:
public class HttpDataService
{
public HttpDataService(string token)
{
this.HttpClient = new HttpClient();
this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
private HttpClient HttpClient { get; set; }
public async Task<object> Get(string controller)
{
object data;
HttpResponseMessage response = await this.HttpClient.GetAsync(UrlService.BuildEndpoint(controller));
if (response.IsSuccessStatusCode)
{
data = await response.Content.ReadAsAsync<object>();
return data;
}
else
{
throw new Exception(); //todo
}
}
}
我不喜欢额外的步骤,我需要为 运行 任务执行方法(Main 方法中的 RunAsync.GetAwaiter...
)。
有没有更简单的方法来使用我自己的端点?也许其他一些不需要额外方法的库(这样,static Async Task Run
)?有没有办法像这样触发方法:
http.Get("Projects");
没有我之前写的RunAsync()
方法?
PS。该控制台应用程序工作正常(我从我的 WebApi 项目的 Default
控制器获取值)
编辑
这样看起来更人性化:
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Task get = http.Get("default");
RunAsync(get).GetAwaiter().GetResult();
}
static async Task RunAsync(Task endpoint)
{
await endpoint;
}
但是如何从 endpoint
中获取?
您的代码有 2 个问题。第一个是你的 RunAsync
方法 returns Task
而你的方法 HttpDataService.Get
return Task<object>
。要从端点获得结果,RunAsync
应该 return Task<object>
。当你等待这个任务时,你会得到一个包含你结果的对象。
对于.GetAwaiter().GetResult()
,有2个选项。首先,您可以创建一个 static async Task MainAsync
并在其中 运行 所有代码并通过调用 MainAsync().GetAwaiter().GetResult()
从非同步 Main
方法调用此方法。在 C# 7.1 之前,这是要走的路。
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
static async Task MainAsync(string[] args)
{
// Run your async code here
}
如果您使用 C# 7.1,您可以使您的 Main
-方法异步 (static async Task Main(string[] args)
),然后您可以从那里直接调用您的异步代码。
static async Task Main(string[] args)
{
// Run your async code here
}
你可以使用助手class
public static class AsyncHelper
{
private static readonly TaskFactory _taskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
=> _taskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
public static void RunSync(Func<Task> func)
=> _taskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
允许你这样做:
static async Task RunAsync(Task endpoint) {
AsyncHelper.RunSync(() => endpoint());
}
PS。看看这里 Ms AsyncHelper and here C# Async Tips & Tricks
你应该Main
异步。
注意:仅适用于现代 c#
static async Task Main(string[] args)
{
var result = await http.Get("default");
}