【发布时间】:2017-09-17 15:50:30
【问题描述】:
我有这种情况,我正在研究需要将通知消息发送到公司所有工作站的位置。我们有一个处理桌面通知的客户端服务,它是一个非常简单的 WebApi。
问题/要求 如何从服务器/ASP.Net Web 应用程序异步和并行向所有这些机器发送请求,并捕获其对自定义日志文件的响应?
在发出通知时,许多机器可能已关闭,或者由于机器可能已停用,dns 可能无法解析。
对当前正在原型化的代码的请求/响应周期需要一个非阻塞的周期。这样用户就不必等待所有这些机器的响应。
我的作业: 我了解异步操作更适合 IO 绑定操作,但是机器数量如此之多,让我感到并行和异步 在一起,可能更适合这种情况。
我已设置 ServicePointManager.DefaultConnectionLimit = 10000
HttpClient 的构造函数带有 dispose 选项为 false 已通过。请参阅下面的代码 - 工厂类。
框架中的 HttpClient 类是为重用而设计的,但是据我了解,某些属性不会像基地址一样更改。来源:HttpClient - This instance has already started
我正在使用请求/响应特定 ID(相关 ID)来确保所有异步和并行操作都针对给定请求在同一个文件夹中进行。
TaskCanceledException catch 块永远不会被命中!!
超时已延长至 30 秒,我确信这已经足够了。
原型代码:
public class HttpClientFactory : IHttpClientFactory
{
public void CreateClient(string baseUrl, Action<HttpClient> methodToExecute)
{
using (var handler = new HttpClientHandler())
{
handler.AllowAutoRedirect = true;
using (var client = new HttpClient(handler, false))
{
client.BaseAddress = new Uri(baseUrl);
client.Timeout = TimeSpan.FromSeconds(30);
methodToExecute(client);
}
}
}
}
IHttpClientFactory 是瞬态的 (IoC)
workstationUrls.ForEach(baseUrl =>
{
_httpClientFactory.CreateClient(baseUrl, async (client) =>
{
await client.PostAsync(resourceUrl, content).ContinueWith(t =>
{
try
{
var response = t.Result;
var workstationResponse = new WorkstationResponse
{
StatusCode = (int)response.StatusCode,
Response = response.Content.ReadAsStringAsync().Result
};
workstationResponse.IsSuccess
= workstationResponse.StatusCode >= 200 &&
workstationResponse.StatusCode <= 299
? true
: false;
var docContent = JsonConvert.SerializeObject(workstationResponse);
if (workstationResponse.IsSuccess)
{
// Write workstation log
File.WriteAllText(path
+ "\\Bulk Notifications\\"
+ userFolder + "\\Success\\"
+ GetWorkstationNameFromUrl(baseUrl)
+ GetUniqueTimeStampForFileNames()
+ workstationResponse.IsSuccess + ".txt",
docContent);
}
else
{
// Write workstation log
File.WriteAllText(path
+ "\\Bulk Notifications\\"
+ userFolder + "\\Fail\\"
+ GetWorkstationNameFromUrl(baseUrl)
+ GetUniqueTimeStampForFileNames()
+ workstationResponse.IsSuccess + ".txt",
docContent);
}
}
catch (TaskCanceledException exe)
{
}
catch (Exception ex)
{
var workstationResponse = new WorkstationResponse
{
Exception = ex,
IsSuccess = false
};
var docContent = JsonConvert.SerializeObject(workstationResponse);
// Write workstation log
File.WriteAllText(path
+ "\\Bulk Notifications\\"
+ userFolder + "\\Fail\\"
+ GetWorkstationNameFromUrl(baseUrl) + " "
+ GetUniqueTimeStampForFileNames() + " "
+ workstationResponse.IsSuccess + ".txt", docContent);
}
});
});
});
原型代码问题: 我在异常消息中收到这些错误,而 StackTrace 似乎没有帮助
- “任务已取消”
- “无法访问已释放的对象。对象名称:'System.Net.Http.StringContent'”
【问题讨论】:
-
首先将操作
Action<HttpClient> methodToExecute更改为返回 Task 的函数,以便您可以等待与HttpClient正确交互的异步方法。这导致了已处理的异常。 -
谢谢彼得,让我试试看是否会有所作为。
标签: c# asp.net asp.net-web-api httpclient dotnet-httpclient