Как запустить асинхронный метод в указанном потоке - PullRequest
0 голосов
/ 22 января 2019

У меня есть приложение (http web app test test), которому требуется new Thread(), а у HttpClient есть только асинхронный метод, так как мне запустить синхронное действие

ps: я пытался использовать полныйTask но номер потока, который он использует, мал (только 30 потоков), поэтому я хочу попробовать Thread, чтобы увидеть, может ли он быть намного быстрее.Будет ли поток .GetAwaiter().GetResult() стоить 2 (поток 100 стал потоком 200)?


предыдущий Я использую

for(var i = 0; i< 200;i++)
{
    Task.Run(async ()=>
    {
        while(thereStillHaveRequestToMake)
        {
        await httpclient.SendAsync() // some thing like this
        }
    });
}

// the prolem is there are only 30-40 Thread in use (From TaskManager)

Поэтому я хочу переключиться на использование потока напрямую

for(var i = 0; i< 200;i++)
{
    new Thread(()=>
    {
        while(thereStillHaveRequestToMake)
        {
            httpclient.SendAsync().GetAwaiter.GetResult()
        }
    });
}

1 Ответ

0 голосов
/ 23 января 2019

У меня есть приложение (приложение для тестирования веб-загрузки), которому нужен новый поток ()

Почему?

HttpClient имеет только асинхронный метод, поэтомуКак запустить действие синхронно

Почему.

Или Как вызвать асинхронный метод из синхронного метода в C #? .

Я пытался использовать полную задачу, но номер используемого потока мал (только 30 потоков),

Задача не является потоком.Мы можем легко проверить это, запустив методы в пуле потоков.Сначала мы устанавливаем ThreadPool, чтобы разрешить только один поток.

class Program
{
  private const int MaxThreads = 1;

  static void Main(string[] args)
  {
    ThreadPool.SetMinThreads(MaxThreads, 1);
    Console.WriteLine(ThreadPool.SetMaxThreads(MaxThreads, 1));
    Task.Run(() => SomeMethod(new StateInfo { Order = 0, WaitFor = 3000 }));
    Task.Run(() => SomeMethod(new StateInfo { Order = 1, WaitFor = 3000 }));
    Task.Run(() => SomeMethod(new StateInfo { Order = 2, WaitFor = 3000 }));
    Console.WriteLine("Main thread does some work, then sleeps.");
    Thread.Sleep(5000);
    Console.WriteLine("Main thread exits.");
  }

  static void SomeMethod(Object stateInfo)
  {
    var si = (StateInfo)stateInfo;
    Console.WriteLine($"Hello from the thread pool. {si.Order}");
    Thread.Sleep(si.WaitFor);
  }

  public class StateInfo
  {
    public int Order { get; set; }
    public int WaitFor { get; set; }
  }
}

Вывод

True

Основной поток выполняет некоторую работу, затем спит.

Привет из пула потоков.1

Привет из пула потоков.2

Выход из основного потока.

Так как у нас есть 1 поток, и мы сказали первым двум методам ждать всего 6 секунд, но основной поток выходит через 5 секундмы никогда не получим сообщение от 3-го метода.Мы можем легко проверить это, изменив MaxThreads = 2, что дает что-то вроде следующего (мы получаем 3 результата, но не обязательно по порядку):

True

Основной поток выполняет некоторую работу, затем спит.

Привет из пула потоков.1

Привет из пула потоков.2

Привет из пула потоков.3

Выход из основного потока.

Теперь, когда мы убедились, что используем один поток, давайте посмотрим, сколько запросов мы можем выполнить одновременно синхронно .

static void SomeMethod(Object stateInfo)
{
  var si = (StateInfo)stateInfo;
  Console.WriteLine($"Hello from the thread pool. {si.Order}");
  httpClient.GetStringAsync($"https://www.google.com");
  Console.WriteLine($"Hello from the thread pool. {si.Order} finished");
}

Поскольку мы не async / await запрос, он выполняет синхронно , поэтому вывод будет предсказуемым:

True

Основной поток выполняет некоторую работу, затем спит.

Привет из пула потоков.1

Привет из пула потоков.1 закончено

Привет из пула потоков.2

Привет из пула потоков.2 закончено

Привет из пула потоков.3

Привет из пула потоков.3 завершено

Выход из основного потока.

Это на самом деле ничего не загружает в тест, потому что синхронные вызовы ждут завершения предыдущего.Для загрузки теста нам нужно много одновременных вызовов.Это легко сделать с помощью одного потока, используя async await.

Обновите метод:

static async Task SomeMethod(Object stateInfo)
{
  var si = (StateInfo)stateInfo;
  Console.WriteLine($"Hello from the thread pool. {si.Order}");
  await httpClient.GetStringAsync($"https://www.google.com");
  Console.WriteLine($"Hello from the thread pool. {si.Order} finished");
}

Используйте linq, чтобы составить список запросов, и дождитесь завершения всех из них.

static void Main(string[] args)
{
  ThreadPool.SetMinThreads(MaxThreads, 1);
  Console.WriteLine(ThreadPool.SetMaxThreads(MaxThreads, 1));

  Console.WriteLine("Start Requests");
  var requests = Enumerable.Range(0, 200)
    .Select(async (x) => await Task.Run(() => SomeMethod2(new StateInfo { Order = x, WaitFor = 0 })))
    .ToArray();

  Console.WriteLine("Wait for them.");
  Task.WaitAll(requests.ToArray());

  Console.WriteLine("Main thread exits.");
  Console.ReadKey();
}

Выходы (я не хотел помещать здесь 400 строк кода)

True

Стартовые запросы

Ждать их.

Привет из пула потоков.0

Привет из пула потоков.1

Привет из пула потоков.2

.... повторяется до

Hello из пула потоков.199

Привет из пула потоков.178 закончено

Привет из пула потоков.5 закончено

Привет из пула потоков.3 закончено

Привет из пула потоков.15 закончено

Привет из пула потоков.26 закончено

Привет из пула потоков.4 выполнено

.... повторяется до тех пор, пока не завершатся все 200 запросов

Выход из основного потока.

200 Запросы Http в одном потоке.Зачем вам больше ниток?

...