2014-06-14 27 views
5

Tôi có một dự án web yêu cầu số liệu thống kê/nhật ký trên trang web được cập nhật từ dịch vụ xà phòng bên ngoài. Cách tiếp cận mà tôi đã quyết định thực hiện với điều này là sử dụng signalR, bằng cách mã có thể thực hiện một phương thức dịch vụ và trả về kết quả cho tất cả các máy khách được kết nối. Mã này sẽ được thực hiện liên tục, với sự chậm trễ giữa các cuộc gọi dịch vụ.Nhắn tin liên tục SignalR

Tôi đang gặp khó khăn khi đặt tất cả các phần lại với nhau, có lẽ vì tôi không chắc chắn mọi thứ nên đi! Đây là một sự cố thô vào những gì tôi đã làm cho đến nay

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); 
     } 
    } 
} 

Vì vậy, ở trên là logic mà được dữ liệu từ các dịch vụ bên ngoài, và thực hiện một cuộc gọi lại. Đối với signalR, điều duy nhất tôi đã làm như sau

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 
     }); 
    } 
} 

Phương pháp GetData() có thể được gọi khi khách hàng kết nối (nếu nó chưa được chạy) và các thẻ có thể bị hủy bỏ khi không có nhiều khách hàng hơn được kết nối với trung tâm.

(tiềm năng) Vấn đề:

  1. hub SignalR không độc thân chúng là gì? Tôi cho rằng chúng được tạo ra khi cần và xử lý khi không cần nữa (yêu cầu đã hoàn thành). Trong trường hợp này, tôi sẽ có nhiều trường hợp của phương thức GetData đang chạy (trừ khi tôi làm cho lớp DataService là một singleton/được tiêm dưới dạng một singleton).
  2. Trung tâm không giống như nơi thích hợp để thực hiện việc này. Một trung tâm nên được xử lý như một bộ điều khiển MVC/Web Api? Vì vậy, một yêu cầu đến, hub xử lý nó, yêu cầu được hoàn thành. Kết thúc câu chuyện.
  3. Một cách khác để thực hiện việc này là chuyển trung tâm vào dịch vụ dữ liệu. Và sau đó nó có thể gọi cho khách hàng. Nhưng tôi không thực sự muốn đi qua các đối tượng IHubContext. Tôi muốn giữ dịch vụ càng đơn giản càng tốt.
  4. Tác vụ nền ASP.NET có phù hợp hơn ở đây không?

Xin cảm ơn nếu ai đó có thể chỉ cho tôi đúng/cách tiếp cận tốt nhất!

+0

* Chào mừng bạn đến với StackOverflow! * Vui lòng xem ["Câu hỏi có nên bao gồm" thẻ "trong tiêu đề của họ không?"] (Http://meta.stackexchange.com/questions/19190/should-questions-include-tags-in- danh hiệu của họ), nơi sự đồng thuận là "không, họ không nên". –

Trả lời

1

Tôi đã quản lý để giải quyết vấn đề này bằng cách sử dụng giao diện IRegisteredObject trong không gian tên System.Web.Hosting.Vì vậy, tác vụ được lập biểu của tôi là:

public class DataTask : IRegisteredObject 
{ 
    private readonly IGlobalData _global; 
    private readonly IDataService _service; 
    private readonly IHubContext _hub; 

    private Timer _timer; 

    public DataTask(IGlobalData global, IDataService service, IHubContext hub) 
    { 
      this._global = global; 
      this._service = service; 
      this._hub = hub; 

      var interval = new TimeSpan(0, 0, 10); 
      this._timer = new Timer(updateClients, null, TimeSpan.Zero, interval); 

      // register this task with asp.net 
      HostingEnvironment.RegisterObject(this); 
    } 

    public void Stop(bool immediate) 
    { 
      _timer.Dispose(); 

      HostingEnvironment.UnregisterObject(this); 
    } 

    private async void updateClients(object state) 
    { 
      var result = await this._service.GetData(); 
      // call the hub 
      this._hub.Clients.All.updateData(result); 
    } 
} 

Tôi đã có một số vấn đề! Nhưng điều này là do trình phân giải phụ thuộc tùy chỉnh mà tôi đã sử dụng cho signalR (vấn đề là chức năng khách hàng js không được gọi từ nhiệm vụ này). Một khi đã được giải quyết, mọi thứ hoạt động như mong đợi.

3

Tôi đã tạo một thư viện tách riêng miền của bạn khỏi SignalR, nó sẽ giải quyết vấn đề 1-3 cho bạn.

hãy có một cái nhìn ở đây https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/wiki

Vấn đề 4, bạn hoàn toàn nên sử dụng một nhân viên ASP.NET nền trên một sợi tiêu chuẩn, nếu không ASP sẽ không biết nó tồn tại và tái chế etc ứng dụng

+0

Cảm ơn. Tôi sẽ xem thử! – Umair

+0

Bạn cũng có thể thử bản trình diễn trực tiếp tại đây http://malmgrens.org/signalr/ – Anders

2

1 , 2,4: Tôi sẽ sử dụng một tác vụ nền và sau đó tận dụng lợi thế của lớp Connectionmanager để lấy trung tâm thích hợp. Here bạn tìm thêm thông tin về cách thực hiện cuộc gọi từ bên ngoài trung tâm.

3: Để giữ cho các dịch vụ của tôi được sạch sẽ, tôi thường đăng ký dịch vụ nhắn tin đó. Dịch vụ dữ liệu của tôi sau đó gọi một phương thức từ dịch vụ tin nhắn mà nội bộ giải quyết một trung tâm và truyền bá thông điệp. Theo cách này, tôi giữ các dịch vụ dữ liệu của mình gọn gàng vì chúng chỉ gọi một phương thức dịch vụ tin nhắn cụ thể (thường là một lớp lót). Dịch vụ dữ liệu của tôi không cần bất kỳ kiến ​​thức về những gì dịch vụ tin nhắn của tôi đang làm.

+0

Có Tôi đang nghĩ đến việc gói các trung tâm trong một lớp tùy chỉnh và chuyển cho các dịch vụ của tôi. Cảm ơn vì sự trả lời. – Umair

Các vấn đề liên quan