将自托管SignalR服务器添加到.Net Core Worker服务



我正在尝试使用SignalR(自托管web应用程序(扩展.NET核心工作服务(<Project Sdk="Microsoft.NET.Sdk.Worker">(
我找到的所有示例/教程/文档都是基于web应用程序的,所以它们不适合我的情况。

这就是我迄今为止所做的:
我的服务程序.cs:

public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>                       
Host.CreateDefaultBuilder(args)
.UseWindowsService()            
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
DependencyBuilder.Build(hostContext, services);  // inject the stuff I need in my service
// create a SignalR Web host               
SignalRWebHostCreator.CreateHost(services, "http://localhost:8090", (endpoints) => {
endpoints.MapHub<MyHub>("/result");
});
});
}

以及我想用SignalR服务器应用程序"扩展"服务的类。


public class SignalRWebHostCreator
{
public static void CreateHost(IServiceCollection services, string serviceUrl, Action<IEndpointRouteBuilder> mapHubs)
{
services.AddSignalR();  // is it ok here ?
WebHost.CreateDefaultBuilder()
.UseUrls(serviceUrl)
.Configure((IApplicationBuilder app) => {
app.UseRouting();
app.Map("/check", config => {  // just a test: it works!
config.Run(async context =>
{   
context.Response.ContentType = "text/plain";
byte[] data = System.Text.Encoding.UTF8.GetBytes("OK");
await context.Response.Body.WriteAsync(data, 0, data.Length);
await context.Response.Body.FlushAsync();
});
});
app.UseEndpoints(endpoints =>
{
//endpoints.MapHub<ClockHub>("/hubs/clock");   // ERROR
//endpoints.MapHub<PingHub>("/ping");  // ERROR
//mapHubs(endpoints);    // ERROR
});
})
.Build().Run();
}
}

(ClockHub取自MS示例,PingHub是我尝试使用的另一个简单集线器,而不是我的"注入"集线器(

它正确启动web应用程序,并正确响应urlhttp://localhost:8090/check

当我取消注释对enpoint.MapHub()或我的cusom Actions的调用时,我会出现以下错误:

System.InvalidOperationException:'找不到所需的服务。请通过在应用程序启动代码中对"ConfigureServices(…("的调用中调用"IServiceCollection.AddSignalR"来添加所有必需的服务

第二次尝试:
看起来service.AddSignalR()没有完成它的工作,所以我在SignalRWebHostCreator中添加了这个:

.Configure((IApplicationBuilder app) => {
app.ApplicationServices = services.BuildServiceProvider();

现在我遇到了以下错误:
System.InvalidOperationException"在尝试激活"Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware"时无法解析类型为"System.Diagnostics.DiagnosticListener"的服务。">

至少有一个调用堆栈:
_此异常最初是在此调用堆栈引发的:
Microsoft.Extensions.Interal.ActivatorUtilities.CConstructorMatcher.CreateInstance(System.IServiceProvider(
Microsoft.Extensions.Ineral.Activator Utilities.CreateInstance(System.IServiceProvider,System.Type,object[](
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.UseMiddleware.AnoymousMethod__0
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Sthrow((
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess

如果我添加services.AddSingleton(new System.Diagnostics.DiagnosticListener("diagnostic listener"));,我可以使用endpoints.MapHub(..)而不会出错,但现在调用http://8090/check返回一个500内部错误,所以我认为这不是解决问题的正确方法。

我发现了一些使用Microsoft.Owin.hostingWebApp的例子。
它需要Microsoft.Owin.4.10Microsoft.Owin.Hosting4.1.0Owin1.0.0.最后一个需要Net Framework 4.6.1,我不想要这个
我已经包含了Microsoft.AspNetCore.Owin.3.1.2(100%.NET Core(,但它不提供WebApp或类似功能。

当我将nuget EFCore包升级到新版本时,我开始遇到同样的错误。

我注意到,在我的bin目录中,出现了一个System.Diagnostics.DiagnosticSource.dll,而当我降级时,它消失了。

我怀疑,旧程序集版本中的DiagnosticListener类型已在DI容器中注册,而在激活时则需要更新的版本。或者反过来——我没挖那么深。

我的解决方案是将EFCore还原为与System.Diagnostics.DiagnosticSource.dll的产品版本匹配,这样它就不会出现在bin文件夹中。

最新更新