0

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

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

这里有一个快速的代码片段来说明这个问题:

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如果它在桌面上可用,还有一种方法可以潜在地解决上述问题。

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

4

1 回答 1

0

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

在另一个 AppDomain 中调用 Await 时没有 SynchronizationContext

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

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

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

于 2016-04-22T18:34:00.987 回答