Dispatcher Begin Invoke метод, останавливает вызов делегированного метода через несколько минут - PullRequest
0 голосов
/ 10 сентября 2011

Я создаю приложение на C # с использованием WPF, приложению необходимо постоянно подписываться на событие, генерируемое сторонним сервером, и обновлять элементы управления пользовательским интерфейсом на основе полученных событий. Сначала необходимо подключиться к серверу. до того, как события могут быть выданы, соединение является дорогой операцией, поэтому я поместил его в отдельный поток и использовал диспетчер WPF BeginInVoke и метод делегата для подписки на события, теперь проблема в том, что это будет нормально работать некоторое время после Я запускаю приложение, я имею в виду, что элементы управления пользовательского интерфейса будут уведомлены в течение некоторого времени, прежде чем оно прекратит получать уведомление, я попытался поставить точку останова и войти в код, метод, вызываемый делегатом, не вызывается диспетчером, а третий сервер вечеринок постоянно генерирует события, но мой диспетчер не получает их снова, я испробовал все возможные способы, но я не смог найти никакого решения, кто-нибудь с помощью и решения будет признателен

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);
    }     

} }

Ответы [ 2 ]

1 голос
/ 10 сентября 2011

Слушатель, вероятно, выдает исключение. Вы не будете знать об этом, потому что я подозреваю, что вы не вызываете EndInvoke, чтобы присоединиться к исключению в основном потоке.

Измените свой код на это:

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

Когда служба перестает работать, вы получите исключение в главном потоке и сможете определить причину, просмотрев трассировку стека.

Редактировать

В этом нет необходимости, поскольку вы на самом деле используете 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");
0 голосов
/ 10 сентября 2011

Одна из возможностей состоит в том, что модуль 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...