C# 如何通过回调转换为异步方法

C# 如何通过回调转换为异步方法,c#,multithreading,asynchronous,threadpool,C#,Multithreading,Asynchronous,Threadpool,我有以下情况。我正在使用.NET4.5.1 我有一个名为ServiceRequest()的类 请求使用tcpclient与服务器建立连接并从中获取数据 运行ServiceRequest.Start()时,它会启动一个计时器,然后每隔x分钟向服务器发出一次请求。(我目前在服务类中没有线程) 因此,我现在使用它的方式: private List<ServiceRequest> ServiceCommuncators = new List<ServiceRequest>();

我有以下情况。我正在使用.NET4.5.1

我有一个名为
ServiceRequest()
的类

请求使用tcpclient与服务器建立连接并从中获取数据

运行
ServiceRequest.Start()
时,它会启动一个计时器,然后每隔x分钟向服务器发出一次请求。(我目前在服务类中没有线程)

因此,我现在使用它的方式:

private List<ServiceRequest> ServiceCommuncators = new List<ServiceRequest>();

//Load Services To monitor
serviceResp = new EFServiceRepository();
IList<Service> Services = GetAllServices();

//Setup Services
ItterateServices(Services);

//Start Service Requests
StartServiceRequests();

//Functions:
private void ItterateServices(IList<Service> services)
    {
        for (int i = 0; i < services.Count; i++)
        {
            ServiceCommuncators.Add(new ServiceRequest(i, services[i].IpAddress, services[i].Port, services[i].PollInterval, ServicRequestCallBackFunction));
        }
    }

private void StartServiceRequests()
{
  foreach (ServiceRequest s in ServiceCommuncators)
  {
     s.Start();
  }
}

  public void ServicRequestCallBackFunction(ResponseObject response)
    {
        if (response.Successfull)
        {
            RecievedsuccessfulResponse(response);
        }
        else
        {
            // ServiceRequest Failed
            RecievedFailedResponse(response);
        }
    }
private List ServiceCommuncators=new List();
//加载要监视的服务
serviceResp=新的EFServiceRepository();
IList Services=GetAllServices();
//安装服务
服务(服务);;
//启动服务请求
StartServiceRequests();
//职能:
私人服务(IList服务)
{
for(int i=0;i
现在我想让每个请求异步运行

  • 这样做的最佳方式是什么?
    我是否只为每个请求创建一个线程?还是应该使用threadpool?我是线程新手,所以请尝试简单地解释一下,也请注意,一次运行的ServiceRequests不会超过50个。我不确定这是否能在实施过程中发挥作用

  • 我关心的是回调函数,现在,一旦我将每个
    RequestService
    线程化,我是否需要对回调函数执行任何操作,因为它将在任何给定时间从多个不同线程调用


  • 首先,您肯定不想为此手动创建线程。因此,是的,您应该使用线程池。根据所针对的.net framework版本,您可以使用TPL(任务并行库)创建任务以进行服务调用。这些任务使用线程池中的线程执行代码(默认情况下)。可以找到更多信息

    如果使用TPL而不是回调,则可以使用continuations,并在代码执行后运行其他任务。

    您有4个选项

  • 使用
    这可能是最糟糕的选择,因为它没有利用线程池。而且,由于您正在旋转大量线程(每个线程都有大约1Mb的开销,因为每个线程都有自己的堆栈)
  • 使用 这更好,因为它利用了线程池。但是,它不如其他方法灵活,因为它不允许您从回调返回任何内容
  • 使用
    如果出于某种原因,您不能使用async/wait,那么这是一种方法。它利用了ThreadPool,并且在如何使用它方面非常灵活
    StartNew
    返回
    Task
    ,您可以保留该任务,当需要结果时,可以调用“Task.result”,它将阻止调用线程,直到任务完成
  • 使用
    这是目前最简单、最流行的异步方式,这是正确的。它只是(3)的语法糖
  • 要使用async/await,您的方法必须返回
    Task
    ,在您的例子中是
    Task
    。按照约定,方法名称以Async结尾,并具有关键字Async

    在您的示例中,您可以更改ServiceRequest的Start方法,使其异步:

    public async Task<ResponseObject> StartAsync()
    {
      //make the request using await
      //for example return await caller.PerformRequestAsync
      //an important note here, if the method you need to call is not async, you can use await Task.Factory.StartNew<ResponseObject>(method that returns ResponseObject)
    
      return response; //response is an instance of ResponseObject
    }
    

    然后,可以选择使用TPL,也可以使用异步等待语法。但要做到这一点,您仍然需要创建任务来执行异步代码。这里有更多的信息。因此,你所说的方法,我会去生成我的所有任务。将所有任务保存在列表中。然后去异步执行所有任务?@Zapnologica我将添加一个如何在cas中使用async await的示例。谢谢,我正在考虑去await asyn。特别是我正在使用EF将响应保存在回调函数中,所以我现在使用system.timer每x秒调用一次事件。我应该不这样做吗?@Zapnologica我可能会做的是仍然使用计时器,但在计时器的事件处理程序中,异步执行所有请求(答案中看起来像
    StartServiceRequestsAsync
    )。顺便说一下,我刚刚想起还有另一种使用线程池的方法。通过不过我不推荐,这可能是使用ThreadPool最难的方法哦,让我看看我是否理解正确。我应该得到所有服务的列表,然后我应该在其中循环并为每个服务创建一个计时器,但是在timers do事件中,我将只生成一个ServiceRequestAsync()(而不是生成一个包含计时器的ServiceRequest)这样,我也可以在应用程序运行时更新服务的信息,然后在运行时接受这些更改。AK I在正确的轨道上?这种方法在线程方面有什么好处?
    private async void StartServiceRequestsAsync()
    {
      IEnumerable<Task<ResponseObject>> requests = new List<Task<ResponseObject>>();
      foreach (ServiceRequest s in ServiceCommuncators)
      {
         requests.Add(s.StartAsync()); //this is non-blocking
      }
    
      foreach(var executingRequest in requests)
      {
         ResponseObject response = await executingRequest;
         //do something with response
      }
    }
    
    int minWorker, minIOC;
    // Get the current settings.
    ThreadPool.GetMinThreads(out minWorker, out minIOC);
    // Change the minimum number of worker threads to 50, but 
    // keep the old setting for minimum asynchronous I/O  
    // completion threads. 
    if (ThreadPool.SetMinThreads(50, minIOC))
    {
        // The minimum number of threads was set successfully.
    }
    else
    {
        // The minimum number of threads was not changed.
    }