Como evitar a tarefa de herdar tarefa pai contexto de chamada Logical

votos
0

Eu estou tentando usar AsyncLocal como um substituto para o armazenamento local thread quando usando Task.Run () e métodos assíncronos. O problema que tenho é que eu preciso o código abaixo para impressão

from t1 t1
from t1 t1
from t2 t2
from t2 t2

Este seria o comportamento se utilizando da linha de armazenamento local, mas em vez disso eu estou recebendo esta saída.

from t1 t1
from t1 t1
from t2 t1
from t2 t1

Exemplo código:

public class ClientClass {

   public static void Main() 
   {
      AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();
      var t1 = Task.Run( async () => {
          string a = _asyncLocalString.Value;
          if (a == null) {
              _asyncLocalString.Value = t1;
          }
          a = _asyncLocalString.Value;
          Console.WriteLine(from t1  + a);
          await Task.Delay(10);
          string b = _asyncLocalString.Value;
          Console.WriteLine(from t1  + b);
          var t2 = Task.Run( async () => {
              string aa = _asyncLocalString.Value;
              if (aa == null) {
                  _asyncLocalString.Value = t2;
              }
              aa = _asyncLocalString.Value;
              Console.WriteLine(from t2  + aa);
              await Task.Delay(10);
              string bb = _asyncLocalString.Value;
              Console.WriteLine(from t2  + bb);

          });
          await t2;
      });
      t1.Wait();
   }
} 
Publicado 27/11/2018 em 18:03
fonte usuário
Em outras línguas...                            


2 respostas

votos
1

Você pode suprimir o fluxo antes de chamar Task.Run e restaurá-lo depois

public class ClientClass {

   public static void Main() 
   {
        AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();
        var t1 = Task.Run(async () =>
        {
            string a = _asyncLocalString.Value;
            if (a == null)
            {
                _asyncLocalString.Value = "t1";
            }
            a = _asyncLocalString.Value;
            Console.WriteLine("from t1 " + a);
            await Task.Delay(10);
            string b = _asyncLocalString.Value;
            Console.WriteLine("from t1 " + b);

            ExecutionContext.SuppressFlow();

            var t2 = Task.Run(async () =>
            {
                string aa = _asyncLocalString.Value;
                if (aa == null)
                {
                    _asyncLocalString.Value = "t2";
                }
                aa = _asyncLocalString.Value;
                Console.WriteLine("from t2 " + aa);
                await Task.Delay(10);
                string bb = _asyncLocalString.Value;
                Console.WriteLine("from t2 " + bb);

            });

            ExecutionContext.RestoreFlow();

            await t2;
        });
        t1.Wait();
   }
} 

dar

from t1 t1
from t1 t1
from t2 t2
from t2 t2
Respondeu 29/11/2018 em 04:32
fonte usuário

votos
0

A única maneira que eu conheço, está usando ThreadPool.UnsafeQueueUserWorkItem :

public class ClientClass {

   public static void Main() 
   {
        AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();
        var t1 = Task.Run(async () =>
        {
            string a = _asyncLocalString.Value;
            if (a == null)
            {
                _asyncLocalString.Value = "t1";
            }
            a = _asyncLocalString.Value;
            Console.WriteLine("from t1 " + a);
            await Task.Delay(10);
            string b = _asyncLocalString.Value;
            Console.WriteLine("from t1 " + b);
            var tcs = new TaskCompletionSource<bool>();
            ThreadPool.UnsafeQueueUserWorkItem(async s =>
            {
                string aa = _asyncLocalString.Value;
                if (aa == null)
                {
                    _asyncLocalString.Value = "t2";
                }
                aa = _asyncLocalString.Value;
                Console.WriteLine("from t2 " + aa);
                await Task.Delay(10);
                string bb = _asyncLocalString.Value;
                Console.WriteLine("from t2 " + bb);
                ((TaskCompletionSource<bool>)s).SetResult(true);
            }, tcs);
            await tcs.Task;
        });
        t1.Wait();
   }
} 
Respondeu 28/11/2018 em 22:23
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more