AsyncLocal & CallContext - Как я могу получить как асинхронные *, так и * удаленные гарантии логического контекста?

Я пытаюсь разработать библиотеку, которая реализует свободно определенный шаблон Ambient Context. Мне нужно учитывать как высокую степень параллелизма, так и удаленного взаимодействия (.NET Framework 4.6.2 ). Кажется, у меня есть 2 варианта: AsyncLocal<T>а такжеCallContext, Я не верю ни одному из этих соображений.

Рассмотрим следующий пример, который демонстрирует удаленную половину моей проблемы:

class Program
{
    static string hello = "Hello from '{0}'! \n\tAsyncID: {1} \n\tContextID: {2} ";

    static void Main(string[] args)
    {
        OperationManager.CallContextOperationID = Guid.NewGuid();
        OperationManager.AsyncLocalOperationID = Guid.NewGuid();

        AppDomain other = AppDomain.CreateDomain("remote");
        SayHello();
        other.DoCallBack(SayHello);

        Console.ReadKey();
    }

    private static void SayHello()
    {
        string statement = string.Format(hello, AppDomain.CurrentDomain.FriendlyName,
            OperationManager.AsyncLocalOperationID,
            OperationManager.CallContextOperationID);
        Console.WriteLine(statement);
    }
}

internal class OperationManager
{
    private static string _slotName = "HelloWorld";
    private static readonly AsyncLocal<Guid> _operationID = new AsyncLocal<Guid>();

    public static Guid AsyncLocalOperationID
    {
        get => _operationID.Value;
        set => _operationID.Value = value;
    }

    public static Guid CallContextOperationID
    {
        get => (Guid)CallContext.LogicalGetData(_slotName);
        set => CallContext.LogicalSetData(_slotName, value);
    }
}

Этот класс создает два идентификатора GUID, сохраняя один в локальном асинхронном режиме, а другой в контексте логического вызова. Затем он запускает новый AppDomain и печатает значения из текущего и удаленного домена.

Пример вывода из этой программы показывает

Hello from 'ConsoleApp1.exe'!
    AsyncID: 4c9e7c3a-fef8-4948-b0f0-896abe7dc2dd
    ContextID: 4b479195-6fe8-43ae-a753-2fb3ccc57530
Hello from 'remote'!
    AsyncID: 00000000-0000-0000-0000-000000000000
    ContextID: 4b479195-6fe8-43ae-a753-2fb3ccc57530

И мы можем видеть, что CallContext сделал это через границу удаленного взаимодействия, в то время как AsyncLocal этого не сделал (не удивительно).

Проблема заключается в том, что я не верю, что смогу использовать CallContext в среде "простого параллелизма" (как изложено Стивеном Клири в этом посте) из-за того, что CallContext является общим для всех потоков. У Стивена есть отличный пример псевдокода в связанном решении, который я не буду здесь дублировать. Этот пример обрисовывает в общих чертах асинхронную часть моей проблемы.

Мои два варианта становятся

AsyncLocal<T>: Работает в среде "простого параллелизма", но выходит за границы удаленного взаимодействия.

CallContextРаботает за пределами удаленного взаимодействия, но не работает в среде "простого параллелизма".

Есть ли здесь третий вариант, который мне не хватает?

0 ответов

Другие вопросы по тегам