对方法的调用进行排队
本文关键字:排队 调用 方法 | 更新日期: 2023-09-27 18:36:45
我有一个C#方法(SendAndGet),它向串行端口发送消息并等待响应或超时。我正在使用System.IO.SerialPort与串行端口通信。
我的应用程序中有几个区域调用 SendAndGet 方法。我有一个计时器,每 100 毫秒调用一次,发生的事件也将调用此方法。我正在寻找一种将这些调用排队的方法,以便我可以允许该方法在允许下一次调用之前完成?不知道该怎么做。在发布之前做了很多谷歌搜索和必应搜索。我认为 TPL 对我不起作用?
事实上,TPL 比以前的选项更容易使用。
我们要做的是创建一个包装SerialPort
的类,公开一个异步方法来发送请求并获得响应,通过单个端口对请求进行排队。
这个类还将有一个私有Task
,表示发出的最后一个请求;当一个新请求进来时,它将向该任务添加一个延续以开始执行其实际工作,然后将自己分配为新的"最后一个任务"。
对于 SendAndGet
方法的实际实现,我们将await
最后一个任务,以便在最后一个任务完成之前不会启动,然后我们可以通过端口发送数据,等待数据接收(异步)并处理结果。 请注意,在您的情况下,您可能希望将方法的返回类型从Task
更改为Task<T>
其中T
是从串行端口解析的实际数据。
public class AsyncSerialPort
{
private SerialPort port;
private Task lastRequest = Task.FromResult(true);
public AsyncSerialPort()
{
//initialize port here
}
public Task SendAndGet()
{
lock (lastRequest)
{
var result = SendAndGetImpl();
lastRequest = result;
return result;
}
}
private async Task SendAndGetImpl()
{
await lastRequest;
//send data to port
var type = await port.WhenDataRecieved();
//process the received data
}
}
我们需要的另一件事是WhenDataRecieved
的实现;某种获取表示何时接收数据的Task
的方法,以便我们可以await
它。
public static Task<SerialData> WhenDataRecieved(this SerialPort port)
{
var tcs = new TaskCompletionSource<SerialData>();
SerialDataReceivedEventHandler handler = null;
handler = (s, args) =>
{
tcs.TrySetResult(args.EventType);
port.DataReceived -= handler;
};
port.DataReceived += handler;
return tcs.Task;
}