2012-12-05 59 views
2

當頁面加載時,我在集線器中啓動一個新任務。此任務將數據發送到更新某個html元素的瀏覽器。當我離開頁面瀏覽時,我想停止任務。signalR OnDisconnected()取消任務

問題是,在任務停止之前(由於它是睡眠參數),在此任務的上一個實例有機會停止之前設置了新的tokenSource = new CancellationTokenSource();

我想要做的是當從頁面瀏覽到不需要signalR的不同頁面時停止任務。但也許,如果只是同一頁面的刷新,不要阻止它。不知道該怎麼做。總結起來,我想保證這個任務只有一個實例正在運行(並且只在需要它或者有一個監聽器的頁面上) 任何信息都非常感謝。 感謝

CODE:

public class TaskActionStatus : Hub 
{ 
    #region Static Fields 

    /// <summary> 
    /// The token source. 
    /// </summary> 
    private static CancellationTokenSource tokenSource; 

    /// <summary> 
    /// The url string. 
    /// </summary> 
    private static string url = string.Empty; 

    #endregion 

    #region Public Methods and Operators 

    /// <summary> 
    /// The get tasks status. 
    /// </summary> 
    /// <param name="siteId"> 
    /// The site id. 
    /// </param> 
    /// <param name="location"></param> 
    public void GetTasksStatus(int? siteId) 
    { 
     var taskRepository = UnityContainerSetup.Container.Resolve<ITaskRepository>(); 

     tokenSource = new CancellationTokenSource(); 
     CancellationToken ct = tokenSource.Token; 

     // init task for checking task statuses 
     var tasksItem = new DownloadTaskItem(); 

     // start task only if at least one listener 
     if (UserHandler.ConnectedIds.Count < 2 && !taskRepository.IsTasksStatusAsyncRunning()) 
     { 
      taskRepository.GetTasksStatusAsync(siteId, tasksItem, ct); 

      // subscribe to event [ listener ] 
      tasksItem.Changed += this.UpdateTasksStatus; 
     } 
     else tokenSource.Cancel(); 
    } 

    /// <summary> 
    /// The on connected. 
    /// </summary> 
    /// <returns> 
    /// The <see cref="Task"/>. 
    /// </returns> 
    public override Task OnConnected() 
    { 
     UserHandler.ConnectedIds.Add(this.Context.ConnectionId); 
     return base.OnConnected(); 
    } 

    /// <summary> 
    /// The on disconnected. 
    /// </summary> 
    /// <returns> 
    /// The <see cref="Task"/>. 
    /// </returns> 
    public override Task OnDisconnected() 
    { 
     UserHandler.ConnectedIds.Remove(this.Context.ConnectionId); 
     if (UserHandler.ConnectedIds.Count == 0) 
     { 
      try 
      { 
        tokenSource.Cancel(); 
      } 
      catch (Exception ex) 
      { 
       Log.Error(ex); 
      } 
     } 

     return base.OnDisconnected(); 
    } 

    /// <summary> 
    /// The update tasks status. 
    /// </summary> 
    /// <param name="sender"> 
    /// The sender. 
    /// </param> 
    /// <param name="e"> 
    /// The e. 
    /// </param> 
    public void UpdateTasksStatus(object sender, TaskEventArgs e) 
    { 
     this.Clients.All.updateMessages(e.Tasks); 
    } 

    #endregion 
} 

/// <summary> 
/// The user handler. 
/// </summary> 
public static class UserHandler 
{ 
    #region Static Fields 

    /// <summary> 
    /// The connected ids. 
    /// </summary> 
    public static HashSet<string> ConnectedIds = new HashSet<string>(); 

    #endregion 
} 


    public bool IsTasksStatusAsyncRunning() 
    { 
     if (tasksStatusAsync != null && tasksStatusAsync.Status.Equals(TaskStatus.Running)) 
     { 
      return true; 
     } 

     return false; 
    } 
+0

頁面刷新和導航沒有區別。由於javascript代碼不再運行,因此都會中斷連接。我不確定你可以在OnDisconnected中檢測到。 – davidfowl

回答

2

移動這條線:

  tokenSource = new CancellationTokenSource(); 
      CancellationToken ct = tokenSource.Token; 

... 使得這樣的:

 if (UserHandler.ConnectedIds.Count < 2) 
     { 
      Trace.WriteLine("GetTasksStatus: Starting new task"); 

      tokenSource = new CancellationTokenSource(); 
      CancellationToken ct = tokenSource.Token; 

      taskRepository.GetTasksStatusAsync(siteId, tasksItem, ct); 

      // subscribe to event [ listener ] 
      tasksItem.Changed += this.UpdateTasksStatus; 
     } 

爲我做。謝謝