Can't set synchronization context when using appdomains
Asked Answered
G

1

0

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.

Gretchengrete answered 27/2, 2015 at 5:32 Comment(3)
The SynchronizationContext is thread specific. Is calling the Do() method causing it to be executed on different threads each time? Try outputting the thread id inside the Do() method and check for that.Spaniard
Yes, I am aware of that. No thread creation is employed. I edited the question to illustrate that the thread is the same.Gretchengrete
With the instance residing in a different AppDomain it means that a client/proxy are created. Maybe they are interfering in some way?Spaniard
F
0

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.

Fayfayal answered 22/4, 2016 at 18:34 Comment(1)
Thanks for your answer! Personally, I ended up explicitly resetting synchronization context each time in every callback I make. Taking into account so many kinks .NET gave me along the way, that one seems childishly innocuous.Gretchengrete

© 2022 - 2024 — McMap. All rights reserved.