我的多线程 HttpClient 有什么问题吗?
Are there any issues with my multithreaded HttpClient?
所以在接触了 Java 和 HttpClient 之后,我决定过渡到 C# 以尝试在提高速度的同时降低内存使用量。我一直在阅读这里的成员提供的关于异步与多线程的大量文章。看起来多线程将是更好的方向。
我的程序将访问服务器并反复发送相同的请求,直到检索到 200 代码。原因是因为在高峰时段交通非常高。它使服务器很难到达并抛出 5xx 错误。代码非常简单,我还不想添加循环以帮助观众简化代码。
我觉得我正朝着正确的方向前进,但我想向社区伸出援手,改掉任何坏习惯。再次感谢阅读。
版主注意事项:我要求检查我的代码是否存在差异,我很清楚多线程 HttpClient 是可以的。
using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Net.Http.Headers;
using System.Threading;
namespace MF
{
class MainClass
{
public static HttpClient client = new HttpClient();
static string url = "http://www.website.com";
public static void getSession() {
StringContent queryString = new StringContent("{json:here}");
// Send a request asynchronously continue when complete
var result = client.PostAsync(new Uri(url), queryString).Result;
// Check for success or throw exception
string resultContent = result.Content.ReadAsStringAsync().Result;
Console.WriteLine(resultContent);
}
public static void Run()
{
getSession ();
// Not yet implemented yet..
//doMore ();
}
public static void Main (string[] args)
{
Console.WriteLine ("Welcome!");
// Create the threads
ThreadStart threadref1 = new ThreadStart(Run);
ThreadStart threadref2 = new ThreadStart(Run);
Console.WriteLine("In the main: Creating the threads...");
Thread Thread1 = new Thread(threadref1);
Thread Thread2 = new Thread(threadref1);
// Start the thread
Thread1.Start();
Thread2.Start();
}
}
}
此外,我不确定它是否重要,但我正在 运行 在我的 MacBook Pro 上安装它并计划在我的 BeagleBoard 上 运行 它。
正在阅读 HttpClient 的文档:
此类型的任何 public 静态(在 Visual Basic 中共享)成员都是线程安全的。不保证任何实例成员都是线程安全的。
不要冒险。每个 线程有一个单独的 HTTP 客户端。
您似乎正在阻塞等待回复的线程,并且您是从一个不执行任何额外操作的线程中执行此操作的。那为什么还要用 async/await 呢?您可以使用简单的阻塞调用。
此外 - 您的程序现在在启动线程后立即完成。您可能希望在从 main returning 之前等待线程完成。您可以在程序末尾通过以下代码执行此操作:
Thread1.Join();
Thread2.Join();
根据评论更新:
- 确定您要发出多少个并行请求 - 这将是您的线程数。
- 使用 ManualResetEvent 使主线程等待信号。
- 在每个线程中不断提交您的请求。一旦您得到您正在等待的答案 - 发出 ManualResetEvent 信号并允许您的主要功能 return.
以下方法是thread-safe:
CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync
更多详情:
如果我是你,我会这样做。我会尽可能多地利用异步,因为它比使用线程更有效(你很可能不必一直context-switch,这很昂贵)。
class MainClass
{
public static HttpClient client = new HttpClient();
static string url = "http://www.website.com";
public static async Task getSessionAsync()
{
StringContent queryString = new StringContent("{json:here}");
// Send a request asynchronously continue when complete
using (HttpResponseMessage result = await client.PostAsync(url, queryString))
{
// Check for success or throw exception
string resultContent = await result.Content.ReadAsStringAsync();
Console.WriteLine(resultContent);
}
}
public static async Task RunAsync()
{
await getSessionAsync();
// Not yet implemented yet..
//doMore ();
}
public static void Main(string[] args)
{
Console.WriteLine("Welcome!");
const int parallelRequests = 5;
// Send the request X times in parallel
Task.WhenAll(Enumerable.Range(1, parallelRequests).Select(i => RunAsync())).GetAwaiter().GetResult();
// It would be better to do Task.WhenAny() in a while loop until one of the task succeeds
// We could add cancellation of other tasks once we get a successful response
}
}
请注意,我同意@Damien_The_Unbeliever:如果服务器在高负载下出现问题,您不应添加不必要的负载(执行相同请求的 X 次)并导致服务器出现问题。理想情况下,你会修复服务器代码,但我可以理解它不是你的。
乱用 headers 不是线程安全的。
例如,用新的 OAuth 访问令牌换出不是线程安全的。现在使用 Xamarin 移动应用程序来面对这个问题。我有一个崩溃报告,其中一个线程正在修改 headers 而另一个线程正在尝试请求。
所以在接触了 Java 和 HttpClient 之后,我决定过渡到 C# 以尝试在提高速度的同时降低内存使用量。我一直在阅读这里的成员提供的关于异步与多线程的大量文章。看起来多线程将是更好的方向。
我的程序将访问服务器并反复发送相同的请求,直到检索到 200 代码。原因是因为在高峰时段交通非常高。它使服务器很难到达并抛出 5xx 错误。代码非常简单,我还不想添加循环以帮助观众简化代码。
我觉得我正朝着正确的方向前进,但我想向社区伸出援手,改掉任何坏习惯。再次感谢阅读。
版主注意事项:我要求检查我的代码是否存在差异,我很清楚多线程 HttpClient 是可以的。
using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Net.Http.Headers;
using System.Threading;
namespace MF
{
class MainClass
{
public static HttpClient client = new HttpClient();
static string url = "http://www.website.com";
public static void getSession() {
StringContent queryString = new StringContent("{json:here}");
// Send a request asynchronously continue when complete
var result = client.PostAsync(new Uri(url), queryString).Result;
// Check for success or throw exception
string resultContent = result.Content.ReadAsStringAsync().Result;
Console.WriteLine(resultContent);
}
public static void Run()
{
getSession ();
// Not yet implemented yet..
//doMore ();
}
public static void Main (string[] args)
{
Console.WriteLine ("Welcome!");
// Create the threads
ThreadStart threadref1 = new ThreadStart(Run);
ThreadStart threadref2 = new ThreadStart(Run);
Console.WriteLine("In the main: Creating the threads...");
Thread Thread1 = new Thread(threadref1);
Thread Thread2 = new Thread(threadref1);
// Start the thread
Thread1.Start();
Thread2.Start();
}
}
}
此外,我不确定它是否重要,但我正在 运行 在我的 MacBook Pro 上安装它并计划在我的 BeagleBoard 上 运行 它。
正在阅读 HttpClient 的文档:
此类型的任何 public 静态(在 Visual Basic 中共享)成员都是线程安全的。不保证任何实例成员都是线程安全的。
不要冒险。每个 线程有一个单独的 HTTP 客户端。
您似乎正在阻塞等待回复的线程,并且您是从一个不执行任何额外操作的线程中执行此操作的。那为什么还要用 async/await 呢?您可以使用简单的阻塞调用。
此外 - 您的程序现在在启动线程后立即完成。您可能希望在从 main returning 之前等待线程完成。您可以在程序末尾通过以下代码执行此操作:
Thread1.Join();
Thread2.Join();
根据评论更新:
- 确定您要发出多少个并行请求 - 这将是您的线程数。
- 使用 ManualResetEvent 使主线程等待信号。
- 在每个线程中不断提交您的请求。一旦您得到您正在等待的答案 - 发出 ManualResetEvent 信号并允许您的主要功能 return.
以下方法是thread-safe:
CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync
更多详情:
如果我是你,我会这样做。我会尽可能多地利用异步,因为它比使用线程更有效(你很可能不必一直context-switch,这很昂贵)。
class MainClass
{
public static HttpClient client = new HttpClient();
static string url = "http://www.website.com";
public static async Task getSessionAsync()
{
StringContent queryString = new StringContent("{json:here}");
// Send a request asynchronously continue when complete
using (HttpResponseMessage result = await client.PostAsync(url, queryString))
{
// Check for success or throw exception
string resultContent = await result.Content.ReadAsStringAsync();
Console.WriteLine(resultContent);
}
}
public static async Task RunAsync()
{
await getSessionAsync();
// Not yet implemented yet..
//doMore ();
}
public static void Main(string[] args)
{
Console.WriteLine("Welcome!");
const int parallelRequests = 5;
// Send the request X times in parallel
Task.WhenAll(Enumerable.Range(1, parallelRequests).Select(i => RunAsync())).GetAwaiter().GetResult();
// It would be better to do Task.WhenAny() in a while loop until one of the task succeeds
// We could add cancellation of other tasks once we get a successful response
}
}
请注意,我同意@Damien_The_Unbeliever:如果服务器在高负载下出现问题,您不应添加不必要的负载(执行相同请求的 X 次)并导致服务器出现问题。理想情况下,你会修复服务器代码,但我可以理解它不是你的。
乱用 headers 不是线程安全的。
例如,用新的 OAuth 访问令牌换出不是线程安全的。现在使用 Xamarin 移动应用程序来面对这个问题。我有一个崩溃报告,其中一个线程正在修改 headers 而另一个线程正在尝试请求。