【问题标题】:QueueClient.OnMessage throws StackOverflowException during Worker Role Start upQueueClient.OnMessage 在 Worker 角色启动期间抛出 StackOverflowException
【发布时间】:2018-03-08 21:00:55
【问题描述】:

我正在尝试部署我的第一个 Azure 辅助角色,并且在服务启动期间调用 Run() 方法时遇到此错误。

未知模块中发生了“System.StackOverflowException”类型的未处理异常。

我尝试远程调试我的代码,但在这一行抛出了错误。 MyPublisher 类似于 MyQueue,但它包装了 Topic 而不是 Queue。知道为什么 QueueClient.OnMessage 会导致 StackOverflow 吗?

Client.OnMessage(messageHandler, options);

这里是部分代码。如果格式不正确(将尝试格式化)或代码中缺少任何内容,我深表歉意。

public class MyQueue
{
    String QueueName;
    public QueueClient Client { get; protected set; }

    public MyQueue(String queueName)
    {
        Trace.WriteLine($"Creating service Queue with name : {queueName} ");
        QueueName = queueName;
    }

    public void EstableshConnection(string connectionString = null)
    {
        Trace.WriteLine($"Establishing connection with service Queue : {QueueName} ");
        // Set the maximum number of concurrent connections 
        ServicePointManager.DefaultConnectionLimit = 12;

        connectionString = connectionString ?? CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
        NamespaceManager namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString);
        if (!namespaceManager.QueueExists(QueueName))
            namespaceManager.CreateQueue(QueueName);

        Client = QueueClient.CreateFromConnectionString(connectionString, QueueName);
    }

    public void Send(BrokeredMessage message)
    {
        Trace.WriteLine($"Sending brokered message to queue : {QueueName} ");
        if (Client != null && !Client.IsClosed)
            Client.Send(message);
    }

    public void OnMessage(Action<BrokeredMessage> messageHandler)
    {
        Trace.WriteLine($"OnMessage handler: Queue Name : {QueueName} ");
        OnMessageOptions options = new OnMessageOptions();
        options.AutoComplete = true; // Indicates if the message-pump should call complete on messages after the callback has completed processing.
        options.MaxConcurrentCalls = 1; // Indicates the maximum number of concurrent calls to the callback the pump should initiate 
        options.ExceptionReceived += LogErrors; // Allows users to get notified of any errors encountered by the message pump

//=====================StackOverFlowException on Client.OnMessage======
        if (Client != null && !Client.IsClosed)
            Client.OnMessage(messageHandler, options);  //This is where I get StackOverflowException Error. 
    }

    private void LogErrors(object sender, ExceptionReceivedEventArgs e)
    {
        if (e.Exception != null)
            Trace.WriteLine("Queue client processing error: " + e.Exception.Message);
    }

    public void Disconnect()
    {
        Trace.WriteLine($"closing queue {QueueName}");
        Client.Close();
    }
}

这是我的工作角色实现。

public class MyWorkerRole : RoleEntryPoint
{
    #region Variables
    ManualResetEvent CompletedEvent = new ManualResetEvent(false);

    MyQueue RequestQueue;           //for Request
    MyPublisher ResponseTopicClient;    //ReponseTopic to notify Subscriber when processing is completed

    Public MyWorkerRole()
    {
        RequestQueue = new MyQueue("JobRequestQueue");
        ResponseTopicClient = new MyPublisher("JobCompletedTopic");
    }


    public override bool OnStart()
    {
        try
        {
            RequestQueue.EstableshConnection();
            ResponseTopicClient.EstableshConnection();
        }
        catch (Exception ex)
        {
            Trace.TraceWarning($"Trace: starting service failed. Error {ex.Message} ");
        }
        return base.OnStart();
    }

    public override void OnStop()
    {
        try
        {
            RequestQueue.Disconnect();
            ResponseTopicClient.Disconnect();
            CompletedEvent.Set();
        }
        catch (Exception ex)
        {
            Trace.TraceWarning($"Trace: stopping service failed with error. {ex.Message} ");
        }
        base.OnStop();
    }

    public override void Run()
    {
        try
        {
            Trace.WriteLine("Trace: Starting Message Processing");

            //var receivedMessage2 = RequestQueue.Client.Receive(new TimeSpan(hours: 0, minutes: 2, seconds: 0));
            RequestQueue.OnMessage((receivedMessage) =>
            {
                try
                {
                    Guid resultGuid = (Guid)receivedMessage.Properties["CorrelationGuid"];
                    Trace.TraceWarning($"Trace: processing message with GUID {resultGuid}");

                    var messageToSend = JobProcessor.ProcessRequest(receivedMessage);
                    if (messageToSend == null)
                    {
                        Trace.TraceError("Trace: > Broken message!");
                        receivedMessage.Abandon();
                        return;
                    }
                    ResponseTopicClient.Send(messageToSend);
                    receivedMessage.Complete();
                }
                catch (Exception ex)
                {
                    Trace.TraceError("Trace: Processing exception: " + ex.Message + "\nStack Trace" + ex.StackTrace);
                    Logger.Error("Processing exception: " + ex.Message + "\nStack Trace" + ex.StackTrace);
                }
            });
            CompletedEvent.WaitOne();
        }
        catch (Exception ex)
        {
            Trace.TraceError("Trace: Run exception: " + ex.Message + "\nStack Trace" + ex.StackTrace);
        }
        finally
        {
            CompletedEvent.Set();
        }
    }
}

【问题讨论】:

  • 谢谢。我理解递归,但我只调用一次 Client.OnMessage。 OnMessage 不只是注册在队列中收到实际消息时采取的操作吗?此外,诊断数据并不表明调用了 Action 委托。没有任何东西被发送到队列中,因为我将从单独的应用程序发送请求。我可以尝试从代码中删除主题,看看是否能解决问题,但我想了解这会如​​何影响队列。

标签: c# azure azure-worker-roles azure-queues


【解决方案1】:

当您的工作人员启动时,它会调用 Run 方法,并且在您的代码中,您有:

 //var receivedMessage2 = RequestQueue.Client.Receive(new TimeSpan(hours: 0, minutes: 2, seconds: 0));

RequestQueue.OnMessage((receivedMessage) =>

因此,代码不会等待新消息,因为第一行已被注释,它调用 OnMessage 方法,该方法一次又一次地递归调用自身,直到 StackOverflowException 被触发

在所有情况下,您都需要更改实现,因为StackOverflowException 无论如何都会在收到新消息时发生

【讨论】:

  • Haitham Shaddad,感谢您的回复。我试图简化我的代码来调用 QueueClient.Receive,这给了我同样的错误。我也尝试过在此链接中使用@Abhishek Lal 建议的相同代码,但这也无济于事。
    stackoverflow.com/questions/16714917/… /> 我认为我的问题出在其他地方。
【解决方案2】:

想通了。所以,问题不在于代码。在我的存储帐户下的 WADWindowsEventLogsTable 中报告了以下错误。

错误应用程序名称:WaWorkerHost.exe,版本:2.7.1198.768,时间戳:0x57159090 错误模块名称:Microsoft.IntelliTrace.Profiler.SC.dll,版本:15.0.27128.1,时间戳:0x5a1e2eb9 异常代码:0xc00000fd 故障偏移:0x000000000008ae7b 错误进程ID:0xcf4 错误应用程序启动时间:0x01d3b75ed89dc2f9 错误的应用程序路径:F:\base\x64\WaWorkerHost.exe 错误模块路径:F:\plugins\IntelliTrace\Runtime\x64\Microsoft.IntelliTrace.Profiler.SC.dll

这给了我一个关于禁用 IntelliTrace 的提示,它工作得很好。以下是通过 VS 2017 发布包时如何禁用。

1.) 右键单击​​您的工作角色项目并从菜单中选择发布
2.) 在“设置”页面->“高级设置”中,取消选中“启用 IntelliTrace”选项。

【讨论】:

    猜你喜欢
    • 2013-02-08
    • 2020-09-10
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多