C# 以相同方法处理多个UI Dispatcher问题的可能解决方案?
我在使用多个UI分派器修改绑定到UI的列表时遇到问题。当它到达第一个调度程序时,使用just exit的方法。如果我将整个方法包装在dispatcher中,它可以工作,但我有另一个解决方案,但我不确定它是否合适: 基本上,我有一个套接字,在一个永无止境的循环中监听来自媒体设备的网络命令。当它找到一个时,它调用ProcessCommand 该函数调用50多个方法中的一个来处理特定命令。这些函数存储内部状态,但主要引发我的主应用程序可以订阅的事件,以便它知道卷之类的内容何时发生了更改,我可以更新UI 这些方法工作得很好,除了一开始提到的一种情况,我需要修改一个state对象,该对象在同一个方法中使用多个dispatcher绑定,但它不起作用,并且将该方法包装到一个大dispatcher中似乎是可行的 我发现的另一个解决方案是在UI dispatcher上的套接字后台侦听器中运行ProcessCommand,即: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
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);
}
捕获(例外)