首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >比较SynchronizationContext

比较SynchronizationContext
EN

Stack Overflow用户
提问于 2012-11-21 18:46:56
回答 1查看 1.9K关注 0票数 9

如何比较SynchronizationContext?似乎同一个调度程序在使用SynchronizationContext时可以创建不同的BeginInvoke。当我深入到这两个(不平等)上下文中时,我看到dispatcher线程ID是相同的,但它们并不相等。

代码语言:javascript
复制
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?!?!?
    }        

也许这两个人不能一起用。我注意到这实际上很有效:

代码语言:javascript
复制
        contexta.Send(new SendOrPostCallback((s) =>
            {
                contexte = SynchronizationContext.Current;
            }), null);

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

代码语言:javascript
复制
    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 Ok,我去工作了,但我真的觉得很不舒服。显然,当您发布或发送时,您的任务是从正确的线程运行的,但是如果您不是来自UI,似乎会生成一个新的SynchronizationContext。

代码语言:javascript
复制
    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);
        }
    }

看看这个:

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

EN

回答 1

Stack Overflow用户

发布于 2013-05-29 23:51:01

我想你对BaseCompatibilityPreferences.ReuseDispatcherSynchronizationContextInstance感兴趣。

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

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

  1. 当调用.Send()时,如果您位于正确的线程(不使用dispatcher队列),那么DispatcherSynchronizationContext实际上只会直接调用,因此您不会获得太多的信息(从额外的间接层得到一些检查和调用)。
  2. 如果仅针对WPF进行代码,则可以使用Dispatcher.CheckAccess()和Dispatcher.Invoke()来执行您想做的事情。

在一般情况下,没有办法“比较”两个SynchronizationContexts,所以只需调用.Send()即可。无论如何,这不太可能是性能问题,请记住,早期优化首先是所有有害的->度量的根源。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13500030

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档