停止连接后,SignalR会短暂锁定

时间:2014-04-30 18:27:13

标签: c# javascript .net-4.0 signalr

我正在使用SignalR 1.2.1(因为我们正在实施的项目有.NET 4.0)。

这个过程基本上是:

  • JS客户端启动集线器连接,然后通过调用BeginPolling
  • 开始
  • BeginPollingReportProgress中引用GetProgress / RenewalImportProgress
  • showProgress向客户端显示更新的进度消息
  • importDone是另一种停止连接的客户端方法,显示“完成!”,并重新启用表单字段。

我遇到的问题是,如果我尝试开始第二次导入,或者甚至单击执行简单window.location重定向的按钮(完成后),我会延迟大约5-10秒。其他用户也报告其他机器上的延迟时间长达30秒。

我已启用了客户端日志记录,并且还为signalR设置了stateChanged函数,并且连接说它已关闭,不确定可能导致此延迟/锁定的原因是什么?发生在IE和Chrome中。

var progressNotifier = $.connection.progressHub;

progressNotifier.client.showProgress = function (message) {
    UpdateProgress(message);
};
progressNotifier.client.importDone = function () {
    $.connection.hub.stop(); //stop hub connection

    //delayed to show "Done!" temporarily
    setTimeout(function () {
        $('#message').hide();
        $('input').prop('disabled', false); //enable input fields
        $('#batchName').focus(); //give focus and clear fields
        $('#batchName').val('');
        $('#batchDescription').val('');
    }, 1000);

};

$.connection.hub.start().done(function () {
    $.ajax({
        url: "Import/ImportXmlFile",
        type: 'POST',
        dataType: "json",
        data: JSON.stringify(@Html.Raw(Json.Encode(Model))),
        contentType: 'application/json;charset=utf-8',
    });

    progressNotifier.server.beginPolling("@Model.BATCHID");
});

function UpdateProgress(msg) {
    $("#result").html(msg);
}

ProgressHub.cs:

public class ProgressHub : Hub
{
    private readonly RenewalImportProgress _renewalImportProgress;

    public ProgressHub() : this(RenewalImportProgress.Instance) { }

    public ProgressHub(RenewalImportProgress renewalImportProgress)
    {
        _renewalImportProgress = renewalImportProgress;
    }

    public void BeginPolling(string batchId)
    {
        _renewalImportProgress.GetProgress(batchId);
    }
}

RenewalImportProgress.cs:

public class RenewalImportProgress
{
    private readonly static Lazy<RenewalImportProgress> _instance = new Lazy<RenewalImportProgress>(() => new RenewalImportProgress(GlobalHost.ConnectionManager.GetHubContext<ProgressHub>().Clients));
    private readonly TimeSpan _updateInterval = TimeSpan.FromMilliseconds(1000);
    private readonly Timer _timer;
    private string _batchId;

    private RenewalImportProgress(IHubConnectionContext clients)
    {
        Clients = clients;
        _timer = new Timer(ReportProgress, null, _updateInterval, _updateInterval);

    }
    public static RenewalImportProgress Instance{ get { return _instance.Value; } }
    private IHubConnectionContext Clients { get; set; }

    private void ReportProgress(object state)
    {
        GetProgress(_batchId);
    }

    public void GetProgress(string batchId)
    {
        if (!string.IsNullOrEmpty(batchId)) _batchId = batchId;

        Stats stats;
        var message = "Preparing file...";
        using (var _repository = new ImportRepository())
        {
            stats = _repository.GetImportStats(_batchId);
        }

        if (stats != null && stats.ProcessCount != 0)
        {
            var processedCount = stats.ProcessCount + stats.ErrorCount;
            if (stats.BatchCount > processedCount)
            {
                message = "Processing... " + processedCount.ToString() + " of " + stats.BatchCount.ToString() + " completed.";
                Clients.All.showProgress(message);
            }
            else if (stats.BatchCount == processedCount)
            {
                message = "Processing file... Done!";
                Clients.All.showProgress(message);
                Clients.All.importDone();
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

在您的代码中,如果您的 ReportProgress 方法执行时间超过一秒,则计时器将在另一个线程中同时执行 ReportProgress 。< / p>

不知道这是否会导致问题,但是值得尝试更改计时器以避免在当前执行完成之前再次调用:

private RenewalImportProgress(IHubConnectionContext clients)
{
   Clients = clients;
   _timer = new Timer(ReportProgress, null, _updateInterval, Timeout.Infinite);
}

private void ReportProgress(object state)
{
    GetProgress(_batchId);
    _timer.Change(_updateInterval, Timeout.Infinite);
}

System.Threading.Timer in C# it seems to be not working. It runs very fast every 3 second