异步和单个实例 class 使用模型
Async and a single instance class working with Models
我正在使用 WebApi 委托处理程序将请求转发到另一台服务器。
protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
string requestContent = string.Empty;
UriBuilder forwardUri = new UriBuilder(request.RequestUri);
//remove the proxy port and replace with an Http port
forwardUri.Port = 1900;
//send it on to the requested URL
request.RequestUri = forwardUri.Uri;
HttpClient client = new HttpClient();
if (request.Method == HttpMethod.Get)
{
request.Content = null;
}
try
{
var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
if (response.IsSuccessStatusCode)
{
ManageOnlineRequests(response);
}
return response;
}
catch (Exception ex)
{
return ManageOfflineRequests(request);
}
}
一切正常,但我在 ManageOnlineRequests
上伪缓存了一些数据。为此,我使用单个实例 class,其中包含我要保留的模型的表示,以便我可以模拟响应和 return 处于离线模式时的响应 ManageOfflineRequests
。
我的问题是:由于这是一个内部包含 await
的 Async 方法,访问我在单例 class 中由 [=2] 调用的列表是否存在任何潜在问题=] 和 ManageofflineRequests
?
谢谢
Since this is a Async method that contains a await inside, is there
any potential issues accessing the lists I have inside singleton class
called by the ManageOnlineRequests and ManageofflineRequests?
这不是 async-await
特有的。如果您的缓存在单例中并且被 多个线程 同时访问,那么您的缓存将出现竞争条件。您必须通过使用简单的 lock
或使用并发收集来保存您的数据,例如 ConcurrentDictionary
.
来确保您正确地保护了您的资产
async-await
本身不会生成任何额外线程,除非您明确告诉它(使用 Task.Run
或 Task.Factory.StartNew
)。 await client.SendAsync
将简单地将控制权交给调用线程,直到您的 IO 工作(在本例中为 HTTP 请求)完成,然后通过 IOCP 调用延续。
正如 Yuval 所说,这与 async-await
无关。如果您计划同时使用这些列表,则需要确保它们是线程安全的。
现在,最简单的选择是使用 lock
,但是如果您专门使用 List<T>
,只要您 只阅读,它就保证是线程安全的 从它而不是同时更新它:
It is safe to perform multiple read operations on a List, but issues can occur if the collection is modified while it’s being read
更好的解决方案是使用 Microsoft.Bcl.Immutable
中的 ImmutableList<T>
,因为它是不可变的,所以保证是线程安全的。
我正在使用 WebApi 委托处理程序将请求转发到另一台服务器。
protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
string requestContent = string.Empty;
UriBuilder forwardUri = new UriBuilder(request.RequestUri);
//remove the proxy port and replace with an Http port
forwardUri.Port = 1900;
//send it on to the requested URL
request.RequestUri = forwardUri.Uri;
HttpClient client = new HttpClient();
if (request.Method == HttpMethod.Get)
{
request.Content = null;
}
try
{
var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
if (response.IsSuccessStatusCode)
{
ManageOnlineRequests(response);
}
return response;
}
catch (Exception ex)
{
return ManageOfflineRequests(request);
}
}
一切正常,但我在 ManageOnlineRequests
上伪缓存了一些数据。为此,我使用单个实例 class,其中包含我要保留的模型的表示,以便我可以模拟响应和 return 处于离线模式时的响应 ManageOfflineRequests
。
我的问题是:由于这是一个内部包含 await
的 Async 方法,访问我在单例 class 中由 [=2] 调用的列表是否存在任何潜在问题=] 和 ManageofflineRequests
?
谢谢
Since this is a Async method that contains a await inside, is there any potential issues accessing the lists I have inside singleton class called by the ManageOnlineRequests and ManageofflineRequests?
这不是 async-await
特有的。如果您的缓存在单例中并且被 多个线程 同时访问,那么您的缓存将出现竞争条件。您必须通过使用简单的 lock
或使用并发收集来保存您的数据,例如 ConcurrentDictionary
.
async-await
本身不会生成任何额外线程,除非您明确告诉它(使用 Task.Run
或 Task.Factory.StartNew
)。 await client.SendAsync
将简单地将控制权交给调用线程,直到您的 IO 工作(在本例中为 HTTP 请求)完成,然后通过 IOCP 调用延续。
正如 Yuval 所说,这与 async-await
无关。如果您计划同时使用这些列表,则需要确保它们是线程安全的。
现在,最简单的选择是使用 lock
,但是如果您专门使用 List<T>
,只要您 只阅读,它就保证是线程安全的 从它而不是同时更新它:
It is safe to perform multiple read operations on a List, but issues can occur if the collection is modified while it’s being read
更好的解决方案是使用 Microsoft.Bcl.Immutable
中的 ImmutableList<T>
,因为它是不可变的,所以保证是线程安全的。