调度程序开始调用方法,几分钟后停止调用委托的方法

本文关键字:方法 调用 几分钟 分钟 开始 调度程序 | 更新日期: 2023-09-27 18:08:02

>我正在使用 WPF 使用 C# 构建一个应用程序,该应用程序需要不断订阅由第三方服务器生成的事件,并根据收到的事件更新 UI 控件,最初我需要先连接到服务器才能发出事件,连接是一项昂贵的操作,所以我将该线程放在单独的线程上,并使用了 WPF 调度程序 BeginInVoke 和一个委托订阅事件的方法,现在的问题是这在我运行应用程序后的一段时间内可以正常工作,我的意思是 UI 控件将在停止接收通知之前通知一段时间,我尝试放置停止点并单步进入代码,委托调用的方法没有被调度程序调用,第三方服务器正在继续发出事件,但我的调度程序没有再次拿起它,我已经尝试了所有可能的方法,但我找不到任何解决方案,任何有帮助和解决方案的人都将不胜感激

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using System.Windows.Threading;
using System.Media;
using ClientPhone.Utility;
using System.Threading.Tasks;
using ClientPhone.Core.DAL;
using ClientPhone.Core.Model;
namespace ClientPhone.View
{
/// <summary>
/// Interaction logic for TestView.xaml
/// </summary>
public partial class TestView : Window
{

    private FreeSwitchEventHandler _freeSwitchEventHandler;
    private delegate void EventDelegate(switch_event evt);
    public static NotificationInfo _notificationInfo;        
    private EventDelegate del;

    public TestView()
    {
        InitializeComponent();
        del = new EventDelegate(actual_event_handler);            
        ConnectToServer();
    }
      private void ConnectToServer()
    {
        string err = string.Empty ;
        const uint flags = (uint)(switch_core_flag_enum_t.SCF_USE_SQL | switch_core_flag_enum_t.SCF_USE_AUTO_NAT);
        freeswitch.switch_core_set_globals();/*Next 3 lines only needed if you want to bind to the initial event or xml config search loops */
        freeswitch.switch_core_init(flags, switch_bool_t.SWITCH_FALSE, ref err);
        IDisposable search_bind = FreeSWITCH.SwitchXmlSearchBinding.Bind(xml_search, switch_xml_section_enum_t.SWITCH_XML_SECTION_CONFIG);
         event_bind = FreeSWITCH.EventBinding.Bind("SampleClient", switch_event_types_t.SWITCH_EVENT_ALL, null, event_handler, true);           

    }
    private void event_handler(FreeSWITCH.EventBinding.EventBindingArgs args)
    {
        Dispatcher.BeginInvoke(del, DispatcherPriority.Send,new object[] {     args.EventObj });
    }

    private void actual_event_handler(switch_event evt)
    {
        _eventInfo = _eventHandler.HandleEvents(evt);           
        if (_eventInfo != null && _eventInfo.Callee == _userId)
        {
            if ((!_callState.IsCallIncoming && _eventInfo.State!="hangup")&&   _eventInfo.Caller!=null)
            {
                SetIsAnsweredParameters()
            }
        }
        if (_eventInfo != null && (_eventInfo.ChannelState == "CS_DESTROY" || _eventInfo.ChannelState == "CS_HANGUP"))
        {
    ResetUIState();
         }
}

    private void SetIsAnsweredParameters()
    {
        if (!_isTimercounting)
        {
            _timerMinutes = 0;
            _timerSeconds = 0;
            _callState.IsCallActive = true;
            _isTimercounting = true;
            _soundManager.StopPlayer();
            _timer.Interval = TimeSpan.FromSeconds(1);
            _timer.Start();
            grdNotification.Visibility = Visibility.Visible;
        }
    }

    private void UpdateHistory(string call)
    {            
        lstHistory.Items.Add(call);
    }     

}}

调度程序开始调用方法,几分钟后停止调用委托的方法

侦听器可能正在引发异常。您不会知道它,因为我怀疑您没有调用 EndInvoke 将异常重新加入主线程。

将您的代码更改为以下内容:

Action action = () => ... ;
action.BeginInvoke(action.EndInvoke, null);

当服务现在失败时,你将在主线程上收到异常,并可以通过查看堆栈跟踪来确定导致异常的原因。

编辑

这不应该是必需的,因为您实际上使用的是在 UI 线程上运行Dispatcher.BeginInvoke

我建议添加一些日志记录,并尝试在启用首次机会例外的情况下在Visual Studio中进行调试。

        var op = Dispatcher.BeginInvoke(del, DispatcherPriority.Send, 
                                        new object[] { args.EventObj });
        op.Completed += (s,e) => logger.Debug("Completed");
        op.Aborted += (s,e) => logger.Debug("Aborted");

一种可能性是FreeSwitch模块实际上是将处理程序传递给非托管代码。在这种情况下,GC 不会知道委托实际上是可访问的,并且会收集它。您可以通过创建一个成员字段来存储event_handler委托来测试此理论:

_newEventDelegateMember = new ProperDelegateType(event_handler);
event_bind = FreeSWITCH.EventBinding.Bind("SampleClient",
               switch_event_types_t.SWITCH_EVENT_ALL, null, 
               **_newEventDelegateMember**, true);