Can't set synchronization context when using a

2019-08-29 06:08发布

I have a custom framework where a host application runs an event loop and loads a guest application into a separate app-domain. The guest application has means to take advantage of the event loop via a provided API. I want to make the guest application be able to automatically propagate all continuations onto the event loop much like it's done in .NET GUI applications and the UI thread. Therefore, I create a custom synchronization context which is able to do that.

But the problem is I can't start using this new context. Whenever I try to set it up, it's reset back to null in the next callback across the app-domain boundary.

Here goes a quick code snippet to illustrate the problem:

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());
        }
    }
}

Output:

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

There is also this SynchronizationContext.SetThreadStaticContext method which could potentially solve the above problem if it was available on desktop.

Of course, there is always a way to explicitly set a context in each callback before doing any other work. But that seems a little lousy. Besides that, I can't see an elegant way to solve this chicken-egg problem. It works as expected on Mono by the way.

1条回答
Root(大扎)
2楼-- · 2019-08-29 06:32

You are probably no longer interested in this but your problem is probably simular to mine:

No SynchronizationContext when calling Await in a another AppDomain

I solved this by grabbing the current dispatcher before calling await. (In my case way before)

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

So if I enter RefereshData on the UI thread, I can continue on that thread after the await.

查看更多
登录 后发表回答