2012-12-05 60 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; 
     } 

为我做。谢谢