我有一个抽象的消息接收器,看起来像这样。在此代码中,entity
是Subscription
的名称(例如user
)。
public class AzureMessageReceiver : ITdlMessageReceiver
{
private readonly ServiceBusConnection serviceBusConnection;
private readonly ILogger<AzureMessageReceiver> logger;
public AzureMessageReceiver(ServiceBusConnection serviceBusConnection, ILogger<AzureMessageReceiver> logger)
{
this.serviceBusConnection = serviceBusConnection;
this.logger = logger;
}
public async Task<TdlMessage<T>> ReceiveAsync<T>(string topic, string entity) where T : class
{
try
{
var subscriptionPath = EntityNameHelper.FormatSubscriptionPath(topic, entity);
var messageReceiver = new MessageReceiver(serviceBusConnection, subscriptionPath, ReceiveMode.ReceiveAndDelete);
var message = await messageReceiver.ReceiveAsync();
if (message == null)
{
return null;
}
var messageString = Encoding.UTF8.GetString(message.Body);
return JsonConvert.DeserializeObject<TdlMessage<T>>(messageString);
}
catch (Exception ex)
{
logger.LogError(ex, "Error receiving Azure message.");
return null;
}
}
}
注入的ServiceBusConnection
的构造如下。 注意::相同的连接初始化有效可以将消息写入相同的Topic
和Subscription
。
services.AddSingleton(serviceProvider =>
new ServiceBusConnection(configuration[$"{DurableCommunicationKey}:AzureConnectionString"]));
更新:这是将调用包装到接收方类的代码,并且是接收消息的控制器:
static async void Receive(ITdlMessageReceiver receiver, ILogger logger)
{
while (true)
{
var message = await receiver.ReceiveAsync<TdlMessage<object>>(topic, entity);
if (message != null)
{
logger.LogDebug($"Message received. Topic: {topic}. Action: {Enum.GetName(typeof(TopicActions), message.Action)}. Message: {JsonConvert.SerializeObject(message)}.");
}
Thread.Sleep(sleepTime);
}
}
每次执行此行var message = await messageReceiver.ReceiveAsync();
时,它只会崩溃控制台应用程序。没有Exception
,没有Event Viewer
中的任何内容。
Secondary Connection String
messageReceiver.ReceiveAsync(TimeSpan.FromMinutes(1));
之类的超时时间topic
从主题的名称更改为主题的整个URL(例如https://{...}.servicebus.windows.net/{topicName}
)ReceiveMode
更改为PeekLock
ConfigureAwait(false)
到ReceiveAsync
通话。TimeSpan.Zero
。 注意::这不会不会使应用程序崩溃,但实际上会抛出Exception
并被记录。答案 0 :(得分:1)
async void
应该转换为async Task
,并且您应该等待Task.Delay
而不是调用Thread.Sleep
。如果要异步,则需要一直保持异步
static async Task Receive(ITdlMessageReceiver receiver, ILogger logger) {
while (true) {
var message = await receiver.ReceiveAsync<TdlMessage<object>>(topic, entity);
if (message != null) {
logger.LogDebug($"Message received. Topic: {topic}. Action: {Enum.GetName(typeof(TopicActions), message.Action)}. Message: {JsonConvert.SerializeObject(message)}.");
}
await Task.Delay(sleepTime);
}
}
请尝试使代码一直处于异步状态,是的,但是作为控制台应用程序(单线程),您将可以在Wait()
的{{1}}方法上以以下方式调用Receive
:不会混合会导致异步流问题的调用。
Main