使用 appdomains 时无法设置同步上下文

Posted

技术标签:

【中文标题】使用 appdomains 时无法设置同步上下文【英文标题】:Can't set synchronization context when using appdomains 【发布时间】:2015-02-27 05:32:37 【问题描述】:

我有一个自定义框架,其中主机应用程序运行事件循环并将来宾应用程序加载到单独的应用程序域中。来宾应用程序可以通过提供的 API 来利用事件循环。我想让来宾应用程序能够自动将所有延续传播到事件循环中,就像在 .NET GUI 应用程序和 UI 线程中所做的那样。因此,我创建了一个能够做到这一点的自定义同步上下文。

但问题是我无法开始使用这个新上下文。每当我尝试设置它时,它都会在跨应用域边界的下一个回调中重置回 null

这里有一个快速的代码 sn-p 来说明问题:

using System;
using System.Threading;


class Test : MarshalByRefObject 
    public void Do() 
        Console.WriteLine("TID: 0, SC: 1",
            Thread.CurrentThread.ManagedThreadId,
            SynchronizationContext.Current != null ? "present" : "absent");
        SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
    


static class Program 
    static void Main() 
        try 
            var domain = AppDomain.CreateDomain("Other Domain");
            var obj = (Test)domain.CreateInstanceAndUnwrap(typeof(Test).Assembly.FullName, typeof(Test).FullName);
            obj.Do();
            obj.Do();
         catch (Exception e) 
            Console.WriteLine(e.ToString());
        
    

输出:

TID: 1, SC: absent
TID: 1, SC: absent

还有这个SynchronizationContext.SetThreadStaticContext 方法,如果它在桌面上可用,它可能会解决上述问题。

当然,在进行任何其他工作之前,总有一种方法可以在 each 回调中显式设置上下文。但这似乎有点糟糕。除此之外,我看不到解决这个鸡蛋问题的优雅方法。顺便说一句,它在 Mono 上按预期工作。

【问题讨论】:

SynchronizationContext 是线程特定的。是否调用 Do() 方法导致它每次都在不同的线程上执行?尝试在 Do() 方法中输出线程 ID 并检查。 是的,我知道这一点。不使用线程创建。我编辑了问题以说明线程是相同的。 实例位于不同的 AppDomain 中,这意味着创建了一个客户端/代理。也许他们在以某种方式干扰? 【参考方案1】:

您可能对此不再感兴趣,但您的问题可能与我的类似:

No SynchronizationContext when calling Await in a another AppDomain

我通过在调用 await 之前获取当前调度程序解决了这个问题。 (在我之前的情况下)

protected async void RefreshData()
 
    var dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
    _data = await LoadAsync(_taskId);
    dispatcher.Invoke(() => OnDataChanged());

因此,如果我在 UI 线程上输入 RefereshData,我可以在等待之后继续该线程。

【讨论】:

感谢您的回答!就个人而言,我最终在每次回调时都显式地重置同步上下文。考虑到 .NET 在此过程中给我带来的许多问题,这似乎幼稚无害。

以上是关于使用 appdomains 时无法设置同步上下文的主要内容,如果未能解决你的问题,请参考以下文章

无法在新的 appDomain 中加载程序集

“无法为从窗口上下文发出的同步 http(s) 请求设置 XMLHttpRequest.timeout”是啥意思?

C#基础知识之System.AppDomain类

插件 AppDomains 解决方法

AppDomain.ExecuteAssembly 设置控制台标题

从 AppDomain 卸载 .DLL 需要帮助 - 即使使用 ShadowCopy 仍无法正常工作