无法使用 OWIN Self Host 关闭和启动新的 SignalR

Cannot shut down and start new SignalR using OWIN Self Host

在 1.5 周的重构结束时,这是一堵难撞的墙。

我已经把它降到最低限度,我完全亏本了

我使用 owin selfhost (katana) 启动了一个 SignalR 网络服务器,并连接到它。我关闭它,然后启动它并尝试再次连接它。

在第 时间(第一次工作正常)我在尝试启动连接时遇到错误:

public partial class App : Application
{

    void App_Startup(object sender, StartupEventArgs e)
    {
        using (var server = new TestWebServer()) {
            server.Start();
            using (var hubConnection = new HubConnection(TestWebServer.Host)) {
                var proxy = hubConnection.CreateHubProxy("testHub");
                hubConnection.Start().Wait();
                Debug.Assert(hubConnection.State == ConnectionState.Connected);
            }
        }

        // Makes it here fine

        using (var server = new TestWebServer()) {
            server.Start();
            using (var hubConnection = new HubConnection(TestWebServer.Host)) {
                var proxy = hubConnection.CreateHubProxy("testHub");
                hubConnection.Start().Wait(); //<-throws "Transport timed out trying to connect"
                Debug.Assert(hubConnection.State == ConnectionState.Connected);
            }
        }
    }
}

TestWebServer:

public class TestWebServer : IDisposable {
    public const string Host = "http://localhost:8081/";
    public void Start() {
        if (null != server) return;
        this.server = WebApp.Start(Host, app => {
            var cfg = new HubConfiguration { };
            app.MapSignalR(cfg);
        });
    }
    IDisposable server;

    //Super-duper-for-real disposable https://lostechies.com/chrispatterson/2012/11/29/idisposable-done-right/
    bool _disposed;
    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    ~TestWebServer() {
        Dispose(false);
    }
    protected virtual void Dispose(bool disposing) {
        if (_disposed)
            return;
        if (disposing) {
            if (null == server) return;
            server.Dispose();
            server = null;
        }
        _disposed = true;
    }

}

TestHub

[HubName("testHub")]
public class TestHub : Hub {
    public void Ping() => Clients.All.pong();
}

这是使用 SignalR 2.2.0,我在 .Net 4.5 和 4.6.1 上都试过了

这是我可能知道如何制作的最简单的 SignalR 应用程序,您会发现它可以工作!一次。然后当我处理并再次尝试完全相同的代码时它失败了。

这是怎么回事?我还需要做些什么来处理东西吗?

是的,我试过Thread.Sleep两者之间。

Here is a tester project demonstrating the issue

感谢我的同事 Shamus,他发现 this article 然后怀疑地破解了我的演示项目,直到该死的东西成功。

如果您每次都给HubConfiguration一个Resolver的新实例,您可以停止并重新启动。换句话说 check this nonsense out in the source.

换句话说,做

var cfg = new HubConfiguration { Resolver = new DefaultDependencyResolver() };

为了解决所有问题的美好时光。

SO 目前看来,存储在依赖项解析器中的某些内容没有得到妥善处理。 (由于在网络服务器处置期间发生异常并记录到调试输出,这一事实加剧了这种怀疑)。如果您不是每次都手动创建自己的解析器,那么...恭喜您,您只是在获取包含未正确处理的对象的同一个全局解析器。

所以答案似乎是肯定的,这是一个 SignalR 错误,但也是肯定的,有一个简单的解决方法。