C# 以相同方法处理多个UI Dispatcher问题的可能解决方案?

C# 以相同方法处理多个UI Dispatcher问题的可能解决方案?,c#,windows-runtime,windows-store-apps,winrt-async,C#,Windows Runtime,Windows Store Apps,Winrt Async,我在使用多个UI分派器修改绑定到UI的列表时遇到问题。当它到达第一个调度程序时,使用just exit的方法。如果我将整个方法包装在dispatcher中,它可以工作,但我有另一个解决方案,但我不确定它是否合适: 基本上,我有一个套接字,在一个永无止境的循环中监听来自媒体设备的网络命令。当它找到一个时,它调用ProcessCommand 该函数调用50多个方法中的一个来处理特定命令。这些函数存储内部状态,但主要引发我的主应用程序可以订阅的事件,以便它知道卷之类的内容何时发生了更改,我可以更新UI

我在使用多个UI分派器修改绑定到UI的列表时遇到问题。当它到达第一个调度程序时,使用just exit的方法。如果我将整个方法包装在dispatcher中,它可以工作,但我有另一个解决方案,但我不确定它是否合适:

基本上,我有一个套接字,在一个永无止境的循环中监听来自媒体设备的网络命令。当它找到一个时,它调用ProcessCommand

该函数调用50多个方法中的一个来处理特定命令。这些函数存储内部状态,但主要引发我的主应用程序可以订阅的事件,以便它知道卷之类的内容何时发生了更改,我可以更新UI

这些方法工作得很好,除了一开始提到的一种情况,我需要修改一个state对象,该对象在同一个方法中使用多个dispatcher绑定,但它不起作用,并且将该方法包装到一个大dispatcher中似乎是可行的

我发现的另一个解决方案是在UI dispatcher上的套接字后台侦听器中运行ProcessCommand,即:

                    CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    { 
                       ProcessCommand(command);
                    });
然后,这将逐步渗透到所有50多个ProcessCommandXYZ方法中,在我的主应用程序中,我在多个页面上订阅这些事件,目前我必须在每个页面上使用UI调度程序,因此类似于:

套接字侦听器后台任务>{DispatcherUI ProcessCommand}>ProcessVolumeCommand>Raise OnVolumeChangeEvent>Subscriber更新UI

这样我就不需要将每个事件订阅服务器放入一个dispatcher,但最重要的是用一种方法修复了我在多个dispatcher中遇到的问题:


这似乎是一个好的解决方案吗?

当您订阅在非ui线程上引发的事件时,这是我的解决方案

//subscribe to event
//handler (OnPlayerVolumeChanged) will be invoked on subscriber (UI) thread
var subscriptionToken = EventSubscription.FromEvent<VolumeChangedEventArgs>(
                            handler => _player.VolumeChanged += handler,
                            handler => _player.VolumeChanged -= handler,
                            OnPlayerVolumeChanged,
                            HandlerThreadOption.SubscriberThread);

//unsubscribe
subscriptionToken.Unsubscribe();
//订阅事件
//将在订阅服务器(UI)线程上调用处理程序(OnPlayerVolumeMached)
var subscriptionToken=EventSubscription.FromEvent(
handler=>\u player.VolumeChanged+=handler,
handler=>\u player.VolumeChanged-=handler,
OnPlayerVolumed,
HandlerThreadOption.SubscriberThread);
//退订
subscriptionToken.Unsubscribe();
以下是实施:

public enum HandlerThreadOption
{
    PublisherThread,
    SubscriberThread,
    BackgroundThread
}

public class EventSubscriptionToken : IDisposable
{
    private readonly Action _unsubscribe;


    public EventSubscriptionToken(Action unsubscribe)
    {
        _unsubscribe = unsubscribe;
    }


    public void Unsubscribe()
    {
        _unsubscribe();
    }


    void IDisposable.Dispose()
    {
        Unsubscribe();
    }
}


public static class EventSubscription
{
    public static EventSubscriptionToken FromEvent<TEventArgs>(
        Action<EventHandler<TEventArgs>> addHandler,
        Action<EventHandler<TEventArgs>> removeHandler,
        EventHandler<TEventArgs> handler,
        HandlerThreadOption threadOption)
    {
        var threadSpecificHandler = GetHandler(handler, threadOption);
        addHandler(threadSpecificHandler);

        return new EventSubscriptionToken(() => removeHandler(threadSpecificHandler));
    }

    public static EventSubscriptionToken FromEvent(
        Action<EventHandler> addHandler,
        Action<EventHandler> removeHandler,
        EventHandler handler,
        HandlerThreadOption threadOption)
    {
        var threadSpecificHandler = GetHandler(handler, threadOption);
        addHandler(threadSpecificHandler);

        return new EventSubscriptionToken(() => removeHandler(threadSpecificHandler));
    }


    private static EventHandler<T> GetHandler<T>(EventHandler<T> handler, HandlerThreadOption threadOption)
    {
        switch (threadOption)
        {
            case HandlerThreadOption.PublisherThread:
                return handler;
            case HandlerThreadOption.SubscriberThread:
                return GetCurrentThreadExecutionStrategy(handler);
            case HandlerThreadOption.BackgroundThread:
                return GetBackgroundThreadExecutionStrategy(handler);
            default:
                throw new ArgumentOutOfRangeException("threadOption");
        }
    }

    private static EventHandler GetHandler(EventHandler handler, HandlerThreadOption threadOption)
    {
        switch (threadOption)
        {
            case HandlerThreadOption.PublisherThread:
                return handler;
            case HandlerThreadOption.SubscriberThread:
                return GetCurrentThreadExecutionStrategy(handler);
            case HandlerThreadOption.BackgroundThread:
                return GetBackgroundThreadExecutionStrategy(handler);
            default:
                throw new ArgumentOutOfRangeException("threadOption");
        }
    }

    private static EventHandler<T> GetBackgroundThreadExecutionStrategy<T>(EventHandler<T> action)
    {
        return (sender, e) => Task.Factory.StartNew(() => action(sender, e));
    }

    private static EventHandler GetBackgroundThreadExecutionStrategy(EventHandler handler)
    {
        return (sender, e) => Task.Factory.StartNew(() => handler(sender, e));
    }

    private static EventHandler<T> GetCurrentThreadExecutionStrategy<T>(EventHandler<T> action)
    {
        var currentSynchronizationContext = SynchronizationContext.Current;

        return (sender, e) => PostToSynchronizationContext(currentSynchronizationContext, () => action(sender, e));
    }

    private static EventHandler GetCurrentThreadExecutionStrategy(EventHandler handler)
    {
        var currentSynchronizationContext = SynchronizationContext.Current;

        return (sender, e) => PostToSynchronizationContext(currentSynchronizationContext, () => handler(sender, e));
    }

    private static void PostToSynchronizationContext(SynchronizationContext synchronizationContext, Action action)
    {
        try
        {
            synchronizationContext.Post(state => action(), null);
        }
        catch (Exception ex)
        {
            if (!ex.Message.StartsWith("The operation cannot be completed because the window is being closed", StringComparison.Ordinal))
            {
                throw;
            }
        }
    }
}
公共枚举句柄线程选项
{
发表者阅读,
请阅读:,
背景线索
}
公共类EventSubscriptionToken:IDisposable
{
私人只读操作_取消订阅;
公共事件订阅登录(操作取消订阅)
{
_退订=退订;
}
公开作废取消订阅()
{
_取消订阅();
}
void IDisposable.Dispose()无效
{
取消订阅();
}
}
公共静态类事件订阅
{
公共静态事件SubscriptionToken FromEvent(
动作addHandler,
动作removeHandler,
事件处理程序,
HandlerThreadOption(螺纹选项)
{
var threadSpecificHandler=GetHandler(handler,threadOption);
addHandler(threadSpecificHandler);
返回新的EventSubscriptionToken(()=>removeHandler(threadSpecificHandler));
}
公共静态事件SubscriptionToken FromEvent(
动作addHandler,
动作removeHandler,
事件处理程序,
HandlerThreadOption(螺纹选项)
{
var threadSpecificHandler=GetHandler(handler,threadOption);
addHandler(threadSpecificHandler);
返回新的EventSubscriptionToken(()=>removeHandler(threadSpecificHandler));
}
私有静态EventHandler GetHandler(EventHandler handler,HandlerThreadOption threadOption)
{
开关(螺纹选项)
{
case HandlerThreadOption.PublisherThread:
返回处理程序;
case HandlerThreadOption.SubscriberThread:
返回GetCurrentThreadExecutionStrategy(处理程序);
case HandlerThreadOption.BackgroundThread:
返回GetBackgroundThreadExecutionStrategy(处理程序);
违约:
抛出新ArgumentOutOfRangeException(“threadOption”);
}
}
私有静态EventHandler GetHandler(EventHandler handler,HandlerThreadOption threadOption)
{
开关(螺纹选项)
{
case HandlerThreadOption.PublisherThread:
返回处理程序;
case HandlerThreadOption.SubscriberThread:
返回GetCurrentThreadExecutionStrategy(处理程序);
case HandlerThreadOption.BackgroundThread:
返回GetBackgroundThreadExecutionStrategy(处理程序);
违约:
抛出新ArgumentOutOfRangeException(“threadOption”);
}
}
私有静态EventHandler GetBackgroundThreadExecutionStrategy(EventHandler操作)
{
return(sender,e)=>Task.Factory.StartNew(()=>action(sender,e));
}
私有静态EventHandler GetBackgroundThreadExecutionStrategy(EventHandler)
{
return(sender,e)=>Task.Factory.StartNew(()=>handler(sender,e));
}
私有静态EventHandler GetCurrentThreadExecutionStrategy(EventHandler操作)
{
var currentSynchronizationContext=SynchronizationContext.Current;
return(sender,e)=>PostToSynchronizationContext(currentSynchronizationContext,()=>action(sender,e));
}
私有静态EventHandler GetCurrentThreadExecutionStrategy(EventHandler)
{
var currentSynchronizationContext=SynchronizationContext.Current;
return(sender,e)=>PostToSynchronizationContext(currentSynchronizationContext,()=>handler(sender,e));
}
私有静态void PostToSynchronizationContext(SynchronizationContext SynchronizationContext,Action-Action)
{
尝试
{
synchronizationContext.Post(state=>action(),null);
}
捕获(例外)