我有一个网络项目,需要从外部肥皂服务更新网页上的统计信息/日志。我决定采用的方法是使用 signalR,通过使用执行服务方法并将结果返回给所有连接的客户端的代码。该代码将连续执行,在服务调用之间有一定的延迟。
我无法将所有部分放在一起,可能是因为我不确定所有东西应该放在哪里!这是我迄今为止所做的粗略细分
class Data { ... }
interface IDataService
{
Task GetDataAsync(TimeSpan interval, CancellationToken cancellationToken, Action<Data> callback);
}
class DataService : IDataService
{
private readonly ExternalService _externalService;
public async Task GetDataAsync(TimeSpan interval, CancellationToken cancellationToken, Action<Data> callback)
{
while (!cancellationToken.IsCancellationRequested)
{
var data = await this._externalService.GetData();
callback(data);
await Task.Delay(interval).ConfigureAwait(false);
}
}
}
以上就是从外部服务获取数据,并执行回调的逻辑。至于signalR,我唯一做的事情如下
public class DataHub : Hub
{
private readonly IDataService _service;
public DataHub(IDataService service)
{
this._service = service;
}
public async Task GetData()
{
var tenSeconds = new TimeSpan(0, 0, 10);
var token = new CancellationToken();
await _service.GetDataAsync(tenSeconds, token, d =>
{
// signal all connected clients
});
}
}
The GetData()
当客户端连接时(如果尚未运行)可以调用该方法,并且当没有更多客户端连接到集线器时可以取消令牌。
(潜在问题:
- SignalR 集线器不是单例,是吗?我假设它们是在需要时创建的,并在不再需要时处置(请求已完成)。在这种情况下,我将有多个实例
GetData
方法运行(除非我将 DataService 类设置为单例/作为单例注入)。
- 中心感觉不是执行此操作的正确位置。集线器应该被视为 MVC/Web Api 控制器吗?因此,一个请求进来,集线器处理它,请求完成。故事结局。
- 另一种方法是将集线器传递到数据服务中。然后它可以呼叫客户端。但我真的不想传递 IHubContext 对象。我想让服务尽可能简单。
- ASP.NET 后台任务在这里更合适吗?
如果有人能指出我正确/最好的方法,我将不胜感激!