我有一个在可移植类库中制作的API,需要联系特定于平台的API才能发送HTTP请求。这是我写的在WinRT上执行HTTP POST的方法:
public bool Post(IEnumerable<KeyValuePair<string, string>> headers, string data)
{
bool success = false;
HttpClient client = new HttpClient(new HttpClientHandler {AllowAutoRedirect = false});
foreach (var header in headers)
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
try
{
var task=client.PostAsync(endpoint, new StringContent(data, Encoding.UTF8, "text/xml")).ContinueWith( postTask =>
{
try
{
postTask.Wait(client.Timeout); //Don't wait longer than the client timeout.
success = postTask.Result.IsSuccessStatusCode;
}catch {}
}, TaskContinuationOptions.LongRunning);
task.ConfigureAwait(false);
task.Wait(client.Timeout);
}
catch
{
success = false;
}
return success;
}
尽管这在施加[[any压力时会出现一个有趣的问题。它似乎在内部陷入僵局。就像我创建5个线程并从中发送POST请求一样,此方法将到达它将执行nothing但超时的地方。内容永远不会到达服务器,并且永远不会执行.Continue
代码。但是,如果我串行运行它,甚至运行2或3个线程,也可以正常运行。似乎抛出的线程更多,但性能却成倍恶化]
<system.net>
<connectionManagement>
<add address="*" maxconnection="300" />
</connectionManagement>
</system.net>
或通过代码可以执行此操作
ServicePointManager.DefaultConnectionLimit = 300
我还会考虑在继续中注释掉等待。我认为没有必要。
try { //Comment this line out your handling it in the outside task already //postTask.Wait(client.Timeout); //Don't wait longer than the client timeout. success = postTask.Result.IsSuccessStatusCode; }catch {}
最后,如果上述两件事不起作用,我会尝试注释掉这段代码。
//Task.ConfigureAwait(false);
可能是Task.Wait加上设置Task.ConfigureAwait(false)的组合会导致某种死锁,但我对这不是专家。我只知道我有一些运行多线程的非常相似的代码,而且我的代码中没有Task.ConfigureAwait(false),主要是因为我尝试了HttpClient库,但没有升级到.NET 4.5因此无法使用等待。
当任务为[[complete时,
ContinueWith
将委托排队以运行。因此,无需等待。LongRunning
在这里不需要;这会降低性能,因为您的连续性非常快,根本不需要长时间运行。ConfigureAwait
是没有意义的,因为没有await
(并且无论如何都将返回值丢弃)。Task.Wait
,因为无论如何,该任务已经在该超时之后完成了。我建议您的API使用HTTP,因此请使其异步。如果要在PCL中完全支持Microsoft.Bcl.Async
/async
,则可以使用await
。
public async Task<bool> Post(IEnumerable<KeyValuePair<string, string>> headers, string data) { HttpClient client = new HttpClient(new HttpClientHandler {AllowAutoRedirect = false}); foreach (var header in headers) { client.DefaultRequestHeaders.Add(header.Key, header.Value); } try { var result = await client.PostAsync(endpoint, new StringContent(data, Encoding.UTF8, "text/xml")).ConfigureAwait(false); return result.IsSuccessStatusCode; } catch { return false; } }