gpt4 book ai didi

c# - 比较 SynchronizationContext

转载 作者:太空狗 更新时间:2023-10-29 17:58:24 24 4
gpt4 key购买 nike

如何比较 SynchronizationContext?似乎同一个 Dispatcher 在使用 BeginInvoke 时可以创建不同的 SynchronizationContext。当我深入研究两个(不相等的)上下文时,我发现调度程序线程 ID 相同,但它们彼此不相等。

public partial class MainWindow : Window
{
private SynchronizationContext contexta;
private SynchronizationContext contextb;
private SynchronizationContext contextc;
private SynchronizationContext contextd;

public MainWindow()
{
InitializeComponent();

contexta = SynchronizationContext.Current;

Loaded += MainWindow_Loaded;
}

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
contextb = SynchronizationContext.Current;

Dispatcher.Invoke(() =>
{
contextc = SynchronizationContext.Current;
});

Dispatcher.BeginInvoke(new Action(() =>
{
contextd = SynchronizationContext.Current;
}));

Debug.Assert(contexta != contextb);
Debug.Assert(contexta == contextc); // fails... why?!?!?
Debug.Assert(contexta == contextd); // fails... why?!?!?
Debug.Assert(contextc == contextd); // fails... why?!?!?
}

也许他们两个不能一起使用。我注意到这确实有效:

        contexta.Send(new SendOrPostCallback((s) =>
{
contexte = SynchronizationContext.Current;
}), null);

更新 但奇怪的是,它并不总是有效。

    public override void AddRange(IEnumerable<T> items)
{
if (SynchronizationContext.Current == _context)
{
base.AddRange(items);
}
else
{
_context.Send(new SendOrPostCallback((state) =>
{
AddRange(state as IEnumerable<T>);
}), items);
}
}

例如,永远不会获得匹配的 _context 并永远持续下去。尽管不应该。后一个示例线程实际上最终是相同的,并且有一个上下文,但它是不同的。

Update2 好的,我让它工作了,但我真的对此感到不舒服。显然,当您发布或发送时,您的任务是从正确的线程运行的,但如果您不是来自 UI,则似乎会生成一个新的 SynchronizationContext。

    public override void AddRange(IEnumerable<T> items)
{
if (SynchronizationContext.Current == _context)
{
base.AddRange(items);
}
else
{
_context.Post(new SendOrPostCallback((state) =>
{
if (SynchronizationContext.Current != _context)
SynchronizationContext.SetSynchronizationContext(_context); // called every time.. strange
AddRange(items);
}), null);
}
}

看看这个:

enter image description here

“要求直接调用者完全信任。该成员不能被部分信任或透明的代码使用。” :(

最佳答案

我觉得你有兴趣 BaseCompatibilityPreferences.ReuseDispatcherSynchronizationContextInstance .

此设置指示单个 SynchronizationContext 实例是否用于给定的 Dispatcher 对象。在 .net 4 之前默认为 true,在 .net 4.5 中默认为 false(这是 LukeN 观察到的行为变化)。

现在,如果您的目标只是直接调用而不是调用 .Send(),我会说:

  1. 当调用 .Send() 时,如果您在正确的线程上(不使用调度程序队列),DispatcherSynchronizationContext 实际上只是直接调用,所以您无论如何都不会获得太多 yield (一些检查和从额外的间接层调用)。

  2. 如果您只针对 WPF 进行编码,则可以使用 Dispatcher.CheckAccess() 和 Dispatcher.Invoke() 来执行您想要的操作。

在一般情况下,没有办法“比较”两个 SynchronizationContext,因此您应该只调用 .Send()。无论如何,这不太可能是性能问题,请记住,过早优化是万恶之源 -> 先测量。

关于c# - 比较 SynchronizationContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13500030/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com