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