private static Stack<ErpUser> GetStack() { if (userScopeStack == null ) userScopeStack = new AsyncLocal<Stack<ErpUser>>(); if( userScopeStack.Value == null) userScopeStack.Value = new Stack<ErpUser>(); return userScopeStack.Value; }
public static async Task ValueProperty() { AsyncLocal<int> local = new AsyncLocal<int>(); Assert.Equal(local.Value, 0); local.Value = 1; Assert.Equal(local.Value, 1); local.Value = 0; Assert.Equal(local.Value, 0); }
public HostExecutionContextSwitcher(HostExecutionContext currentContext) { _currentContext = currentContext; // Tie this instance with the current execution context for Revert validation (it must fail if an incompatible // execution context is applied to the thread) _asyncLocal = new AsyncLocal<bool>(); _asyncLocal.Value = true; }
public HttpContextOrExecutionContextLocalInstanceStore() { this.registrationStore = new AsyncLocal<IDictionary<Type, IList<Tuple<Registration, object>>>> { Value = new Dictionary<Type, IList<Tuple<Registration, object>>>() }; this.injectedRegistrations = new AsyncLocal<IDictionary<Type, IList<Registration>>> { Value = new Dictionary<Type, IList<Registration>>() }; }
public async Task QueueUserWorkItem_PreferLocal_ExecutionContextFlowedIfSafe(bool preferLocal, bool useUnsafe) { var tcs = new TaskCompletionSource <int>(); var asyncLocal = new AsyncLocal <int>() { Value = 42 }; if (useUnsafe) { ThreadPool.UnsafeQueueUserWorkItem(s => s.SetResult(asyncLocal.Value), tcs, preferLocal); } else { ThreadPool.QueueUserWorkItem(s => s.SetResult(asyncLocal.Value), tcs, preferLocal); } asyncLocal.Value = 0; Assert.Equal(useUnsafe ? 0 : 42, await tcs.Task); }
public void ValuePersistsAcrossExecutionContextChanges() { var jtLocal = new AsyncLocal <object>(); jtLocal.Value = 1; Func <Task> asyncMethod = async delegate { SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); Assert.Equal(1, jtLocal.Value); jtLocal.Value = 3; Assert.Equal(3, jtLocal.Value); await TaskScheduler.Default; Assert.Equal(3, jtLocal.Value); }; asyncMethod().GetAwaiter().GetResult(); Assert.Equal(1, jtLocal.Value); }
public static async Task CaptureAndRestoreEmptyContext() { AsyncLocal<int> local = new AsyncLocal<int>(); ExecutionContext ec = ExecutionContext.Capture(); local.Value = 12; ExecutionContext.Run( ec, _ => { Assert.Equal(local.Value, 0); local.Value = 56; }, null); Assert.Equal(local.Value, 12); }
public Crawler(string rootUri, int maxDepth) { this.RootUri = rootUri; this.depthCounter = new AsyncLocal <int>(); //add a trailing slash to url if (!this.RootUri.EndsWith("/")) { this.RootUri = this.RootUri + "/"; } MAX_DEPTH_COUNT = maxDepth; var wiproRoot = new Link { Href = rootUri }; this.SiteNode = new TreeNode <Link>(wiproRoot); this.Links = new List <Link>(); }
public static async Task CaptureAndRestoreEmptyContext() { AsyncLocal <int> local = new AsyncLocal <int>(); ExecutionContext ec = ExecutionContext.Capture(); local.Value = 12; ExecutionContext.Run( ec, _ => { Assert.Equal(local.Value, 0); local.Value = 56; }, null); Assert.Equal(local.Value, 12); }
public async Task NoThrowAwaitable_Await_CapturesExecutionContext(bool captureContext) { var awaitableTcs = new TaskCompletionSource <object>(); var asyncLocal = new AsyncLocal <object>(); asyncLocal.Value = "expected"; var testResult = Task.Run(async delegate { await awaitableTcs.Task.NoThrowAwaitable(captureContext); // uses UnsafeOnCompleted Assert.Equal("expected", asyncLocal.Value); }); asyncLocal.Value = null; await Task.Delay(AsyncDelay); // Make sure the delegate above has time to yield awaitableTcs.SetResult(null); await testResult.WithTimeout(UnexpectedTimeout); }
static async Task Invoke(string[] args) { using (var ctx = new MyContext("context 1")) { Func1(); } using (var ctx = new MyContext("context 2")) { Func1(); } using (var ctx = new MyContext("context 3")) { await Task.Run(Func1); await Task.Run(Func1); await Task.Run(Func1); } /*ThreadLocal 针对Thread , 混用Task.Run无效。 ThreadLocal和new Thread().Start()效果等同AsyncLocal和 Task.Run() * new Thread(() => { * Console.WriteLine(""); * }).Start(); */ AsyncLocal <int> threadLocal = new AsyncLocal <int>(); threadLocal.Value = 1; Console.WriteLine("onethread id {0} value:{1} START", Thread.CurrentThread.ManagedThreadId, threadLocal.Value); await Task.Run(async() => { threadLocal.Value = 2; Console.WriteLine("two thread id {0} value:{1}", Thread.CurrentThread.ManagedThreadId, threadLocal.Value); await Task.Run(() => { threadLocal.Value = 3; Console.WriteLine("three thread id {0} value:{1}", Thread.CurrentThread.ManagedThreadId, threadLocal.Value); }); }); Console.WriteLine("onethread id {0} value:{1} START", Thread.CurrentThread.ManagedThreadId, threadLocal.Value); }
/// <summary> /// 内部构造 /// </summary> public static GlobalContext Reset() { if (_local == null) { _local = new AsyncLocal <GlobalContext>(); } else if (_local.Value != null && !_local.Value.IsDisposed) { _local.Value.Dispose(); } _local.Value = IocHelper.Create <GlobalContext>(); if (_local.Value != null) { return(_local.Value); } IocHelper.AddScoped <GlobalContext, GlobalContext>(); _local.Value = IocHelper.Create <GlobalContext>(); return(_local.Value); }
private static T GetValueFromStorage <T>(AsyncLocal <T> threadStorageData, string key) { if (UseThreadStorage) { return(threadStorageData.Value); } if (_externalContextStorage != null && _externalContextStorageKeys != null && _externalContextStorageKeys.Contains(key)) { return(_externalContextStorage.GetValue <T>(key)); } if (HttpContext == null) { return(threadStorageData.Value); } return((T)HttpContext.Items[key]); }
public async Task SocketAsyncEventArgs_ExecutionContextFlowsAcrossReceiveAsyncOperation(bool suppressContext, bool receiveFrom) { using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) using (var saea = new SocketAsyncEventArgs()) { listener.Bind(new IPEndPoint(IPAddress.Loopback, 0)); listener.Listen(1); client.Connect(listener.LocalEndPoint); using (Socket server = listener.Accept()) { var asyncLocal = new AsyncLocal <int>(); var tcs = new TaskCompletionSource <int>(); saea.Completed += (s, e) => tcs.SetResult(asyncLocal.Value); saea.SetBuffer(new byte[1], 0, 1); saea.RemoteEndPoint = server.LocalEndPoint; asyncLocal.Value = 42; if (suppressContext) { ExecutionContext.SuppressFlow(); } try { Assert.True(receiveFrom ? client.ReceiveFromAsync(saea) : client.ReceiveAsync(saea)); } finally { if (suppressContext) { ExecutionContext.RestoreFlow(); } } asyncLocal.Value = 0; server.Send(new byte[] { 18 }); Assert.Equal(suppressContext ? 0 : 42, await tcs.Task); } } }
public async Task SocketAsyncEventArgs_ExecutionContextFlowsAcrossDisconnectAsyncOperation(bool suppressContext) { using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) using (var saea = new SocketAsyncEventArgs()) { listener.Bind(new IPEndPoint(IPAddress.Loopback, 0)); listener.Listen(1); client.Connect(listener.LocalEndPoint); using (Socket server = listener.Accept()) { var asyncLocal = new AsyncLocal <int>(); var tcs = new TaskCompletionSource <int>(); saea.Completed += (s, e) => tcs.SetResult(asyncLocal.Value); bool pending; asyncLocal.Value = 42; if (suppressContext) { ExecutionContext.SuppressFlow(); } try { pending = client.DisconnectAsync(saea); } finally { if (suppressContext) { ExecutionContext.RestoreFlow(); } } asyncLocal.Value = 0; if (pending) { Assert.Equal(suppressContext ? 0 : 42, await tcs.Task); } } } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void FlowsAsyncLocalsToCallback() { // Makes sure that we flow async locals to callback const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"AsyncLocal.tmp")); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext context = new OverlappedContext(); byte[] data = new byte[DATA_SIZE]; AsyncLocal <int> asyncLocal = new AsyncLocal <int>(); asyncLocal.Value = 10; int?result = null; IOCompletionCallback callback = (_, __, ___) => { result = asyncLocal.Value; OnOverlappedOperationCompleted(_, __, ___); }; NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped(callback, context, data); fixed(byte *p = data) { int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Wait for overlapped operation to complete context.Event.WaitOne(); } boundHandle.FreeNativeOverlapped(overlapped); boundHandle.Dispose(); handle.Dispose(); Assert.Equal(10, result); }
public static async Task AsyncLocalAccess() { var source = new ValueTaskCompletionSource(); var task = source.CreateTask(InfiniteTimeSpan, default); var local = new AsyncLocal <int>() { Value = 56 }; var result = Task.Run(async() => { Equal(56, local.Value); await task; Equal(56, local.Value); }); await Task.Delay(100); True(source.TrySetResult()); await result; }
protected ServiceHostLogger( ServiceContext serviceContext, IServiceEventSource eventSource, string eventCategoryName, IConfigurableObjectLoggerOptions options) { this.serviceContext = serviceContext ?? throw new ArgumentNullException(nameof(serviceContext)); this.eventSource = eventSource ?? throw new ArgumentNullException(nameof(eventSource)); this.eventCategoryName = eventCategoryName ?? throw new ArgumentNullException(nameof(eventCategoryName)); this.scope = new AsyncLocal <Scope>(); this.options = options ?? throw new ArgumentNullException(nameof(options)); }
public void FlowContext_SetAfterOnCompleted_FlowsIfExpected(bool flowContext) { var mres = new ManualResetEventSlim(); var mrvts = new ManualResetValueTaskSource <int>(); mrvts.RunContinuationsAsynchronously = true; var al = new AsyncLocal <int>(); al.Value = 42; mrvts.OnCompleted( _ => { Assert.Equal(flowContext ? 42 : 0, al.Value); mres.Set(); }, null, 0, flowContext ? ValueTaskSourceOnCompletedFlags.FlowExecutionContext : ValueTaskSourceOnCompletedFlags.None); mrvts.SetResult(1); mres.Wait(); }
/// <summary> /// 获取当前线程唯一Aop /// </summary> /// <returns></returns> public static AopProvider Get() { #if NET45 || NET451 string contextKey = typeof(AopProvider).FullName; var _aop = CallContext.LogicalGetData(contextKey); if (_aop == null) { _aop = new AopProvider(); CallContext.LogicalSetData(contextKey, _aop); } return(_aop as AopProvider); #else if (_aop.Value == null) { //_aop = new ThreadLocal<AopProvider>(); _aop.Value = new AopProvider(); } return(_aop.Value); #endif }
static async void Do1() { var asyncLocal = new AsyncLocal <int> { Value = 42 }; Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} - Asynclocal value before first await: {asyncLocal.Value}"); var task = Task.Delay(42); await task.ContinueWith(ant => Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} - Asynclocal value in continuewith {asyncLocal.Value}")); Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} - Asynclocal value after first await: {asyncLocal.Value}"); var task2 = Task.Delay(42); task2.GetAwaiter().UnsafeOnCompleted(() => Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} - Asynclocal value in unsafeoncompleted {asyncLocal.Value}")); await task2; Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} - Asynclocal value after second await: {asyncLocal.Value}"); }
public async Task FlowContext_SetAfterOnCompleted_FlowsIfExpected(bool flowContext) { var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var mrvts = new ManualResetValueTaskSource <int>(); mrvts.RunContinuationsAsynchronously = true; var al = new AsyncLocal <int>(); al.Value = 42; mrvts.OnCompleted( _ => { Assert.Equal(flowContext ? 42 : 0, al.Value); tcs.SetResult(); }, null, 0, flowContext ? ValueTaskSourceOnCompletedFlags.FlowExecutionContext : ValueTaskSourceOnCompletedFlags.None); mrvts.SetResult(1); await tcs.Task; }
/// <summary> /// Initializes parts of the object that are common for both inbound and outbound peers. /// </summary> /// <param name="inbound"><c>true</c> for inbound peers, <c>false</c> for outbound peers.</param> /// <param name="peerEndPoint">IP address and port on the side of the peer.</param> /// <param name="network">Specification of the network the node runs on - regtest/testnet/mainnet.</param> /// <param name="parameters">Various settings and requirements related to how the connections with peers are going to be established, or <c>null</c> to use default parameters.</param> /// <param name="dateTimeProvider">Provider of time functions.</param> /// <param name="loggerFactory">Factory for creating loggers.</param> /// <param name="selfEndpointTracker">Tracker for endpoints known to be self.</param> /// <param name="onDisconnected">Callback that is invoked when peer has finished disconnecting, or <c>null</c> when no notification after the disconnection is required.</param> private NetworkPeer(bool inbound, IPEndPoint peerEndPoint, Network network, NetworkPeerConnectionParameters parameters, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory, ISelfEndpointTracker selfEndpointTracker, IAsyncProvider asyncProvider, Action <INetworkPeer> onDisconnected = null, Action <IPEndPoint, Payload> onSendingMessage = null) { this.dateTimeProvider = dateTimeProvider; this.preferredTransactionOptions = parameters.PreferredTransactionOptions; this.SupportedTransactionOptions = parameters.PreferredTransactionOptions & ~TransactionOptions.All; this.State = inbound ? NetworkPeerState.Connected : NetworkPeerState.Created; this.Inbound = inbound; this.PeerEndPoint = peerEndPoint; this.RemoteSocketEndpoint = this.PeerEndPoint; this.RemoteSocketAddress = this.RemoteSocketEndpoint.Address; this.RemoteSocketPort = this.RemoteSocketEndpoint.Port; this.Network = network; this.Behaviors = new List <INetworkPeerBehavior>(); this.selfEndpointTracker = selfEndpointTracker; this.asyncProvider = asyncProvider; this.onDisconnectedAsyncContext = new AsyncLocal <DisconnectedExecutionAsyncContext>(); this.ConnectionParameters = parameters ?? new NetworkPeerConnectionParameters(); this.MyVersion = this.ConnectionParameters.CreateVersion(this.selfEndpointTracker.MyExternalAddress, this.PeerEndPoint, network, this.dateTimeProvider.GetTimeOffset()); this.MessageReceived = new AsyncExecutionEvent <INetworkPeer, IncomingMessage>(); this.StateChanged = new AsyncExecutionEvent <INetworkPeer, NetworkPeerState>(); this.onDisconnected = onDisconnected; this.onSendingMessage = onSendingMessage; string dequeuerName = $"{nameof(NetworkPeer)}-{nameof(this.asyncPayloadsQueue)}-{this.PeerEndPoint.ToString()}"; this.asyncPayloadsQueue = asyncProvider.CreateAndRunAsyncDelegateDequeuer <Payload>(dequeuerName, this.SendMessageHandledAsync); }
public async Task TaskYield_ConfigureAwait_OnCompleted_CapturesExecutionContext(bool captureContext) { var taskResultSource = new TaskCompletionSource <object>(); AsyncLocal <object> asyncLocal = new AsyncLocal <object>(); asyncLocal.Value = "expected"; Task.Yield().ConfigureAwait(captureContext).GetAwaiter().OnCompleted(delegate { try { Assert.Equal("expected", asyncLocal.Value); taskResultSource.SetResult(null); } catch (Exception ex) { taskResultSource.SetException(ex); } }); asyncLocal.Value = null; await taskResultSource.Task; }
private static void VerifyExecutionContextFlow(AsyncLocal <int> asyncLocal, int expectedValue) { Assert.Equal(expectedValue == 0, ExecutionContext.IsFlowSuppressed()); if (ExecutionContext.IsFlowSuppressed()) { Assert.Null(ExecutionContext.Capture()); } VerifyExecutionContext(ExecutionContext.Capture(), asyncLocal, expectedValue); int asyncLocalValue = -1; var done = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem( state => { asyncLocalValue = asyncLocal.Value; done.Set(); }); done.CheckedWait(); Assert.Equal(expectedValue, asyncLocalValue); }
public static void InitialiseSQLite() { if (initialised) { return; } AsyncLocal <IUnitOfWork> asyncUow = new AsyncLocal <IUnitOfWork>(); Directory.CreateDirectory("../../../Data"); var fsql = new FreeSql.FreeSqlBuilder() .UseAutoSyncStructure(true) .UseNoneCommandParameter(true) .UseConnectionString(FreeSql.DataType.Sqlite, "data source=../../../Data/FreeSQL.sqlite;max pool size=5") .UseMonitorCommand(null, (umcmd, log) => Console.WriteLine(umcmd.Connection.ConnectionString + ":" + umcmd.CommandText)) .UseLazyLoading(true) .UseGenerateCommandParameterWithLambda(true) .Build(); BaseEntity.Initialization(fsql, () => asyncUow.Value); initialised = true; }
private static void SetValueToStorage <T>(AsyncLocal <T> threadStorage, T value, string key) { if (UseThreadStorage) { threadStorage.Value = value; } if (_externalContextStorage != null && _externalContextStorageKeys != null && _externalContextStorageKeys.Contains(key)) { _externalContextStorage.SetValue(value, key); } if (HttpContext == null) { threadStorage.Value = value; } else { HttpContext.Items[key] = value; } }
public static async Task AddAndUpdateManyLocals_ValueType(int count) { var locals = new AsyncLocal <int> [count]; for (int i = 0; i < locals.Length; i++) { locals[i] = new AsyncLocal <int>(); locals[i].Value = i; for (int j = 0; j <= i; j++) { Assert.Equal(j, locals[j].Value); locals[j].Value = j + 1; Assert.Equal(j + 1, locals[j].Value); locals[j].Value = j; Assert.Equal(j, locals[j].Value); } } }
/// <summary> /// Creates a new logger provider. /// </summary> /// <param name="stringLog">The underlying string log to which all logs are written. May not be <c>null</c>.</param> /// <param name="formatter">The formatter used to translate log events into single-line strings. May not be <c>null</c>.</param> /// <param name="filter">The filter for determining which log events to log. May not be <c>null</c>.</param> public AnankeLoggerProvider(IStringLog stringLog, Func <LogEvent, string> formatter, Func <string, LogLevel, bool> filter) { if (stringLog == null) { throw new ArgumentNullException(nameof(stringLog)); } if (formatter == null) { throw new ArgumentNullException(nameof(formatter)); } if (filter == null) { throw new ArgumentNullException(nameof(filter)); } m_stringLog = stringLog; m_formatter = formatter; m_filter = filter; m_loggers = new ConcurrentDictionary <string, ILogger>(); m_scopes = new AsyncLocal <ImmutableStack <object> >(); }
public void SuppressFlow_TaskCapturesContextAccordingly(bool suppressFlow) { Assert.False(ExecutionContext.IsFlowSuppressed()); if (suppressFlow) { ExecutionContext.SuppressFlow(); } try { var asyncLocal = new AsyncLocal <int>(); Task.Factory.StartNew(() => asyncLocal.Value = 42, CancellationToken.None, TaskCreationOptions.None, new InlineTaskScheduler()).Wait(); Assert.Equal(suppressFlow ? 42 : 0, asyncLocal.Value); } finally { if (suppressFlow) { ExecutionContext.RestoreFlow(); } } }
public void RunBackgroundTask__Suppress_Execution_Context( [Frozen] ILogger <TaskHelper> logger, TaskHelper sut) { var local = new AsyncLocal <string> { Value = "hello" }; string taskResult = null; var t = sut.ExecuteBackgroundTask(() => { // FireAndForgetTasks ensure that flow is suppressed therefore this value will be null taskResult = local.Value; return(Task.CompletedTask); }); Task.WaitAll(t); Assert.IsNull(taskResult); }
public async Task AwaitTaskScheduler_UnsafeOnCompleted_DoesNotCaptureExecutionContext() { var taskResultSource = new TaskCompletionSource <object>(); AsyncLocal <object> asyncLocal = new AsyncLocal <object>(); asyncLocal.Value = "expected"; TaskScheduler.Default.GetAwaiter().UnsafeOnCompleted(delegate { try { Assert.Null(asyncLocal.Value); taskResultSource.SetResult(null); } catch (Exception ex) { taskResultSource.SetException(ex); } }); asyncLocal.Value = null; await taskResultSource.Task; }
/// <summary> /// 设置当前上下文(框架内调用,外部误用后果未知) /// </summary> /// <param name="context"></param> public static void SetContext(GlobalContext context) { if (null == context || context.IsDisposed) { _local.Value?.Dispose(); _local.Value = null; _local = null; } else if (_local == null) { _local = new AsyncLocal <GlobalContext> { Value = context } } ; else if (_local.Value != context) { _local.Value = context; } }
public DatabasePool(Func <PooledDatabase> createFunc, int maximumRetained = 0, EvictionSettings evictSetting = null) { if (maximumRetained == 0) { maximumRetained = Environment.ProcessorCount * 2; } #if NET45 currentDatabaseLocal = new ThreadLocal <PooledDatabase>(); #else currentDatabaseLocal = new AsyncLocal <PooledDatabase>(); #endif Pool = new ObjectPool <PooledDatabase>(maximumRetained, () => { PooledDatabase db = createFunc(); db.SetPool(this); //设置池 return(db); } , evictSetting, null); }
public async Task ExecutionContext_FlowsIfNotSuppressed(bool suppressed) { using (var listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { listen.Bind(new IPEndPoint(IPAddress.Loopback, 0)); listen.Listen(1); Task <Socket> acceptTask = listen.AcceptAsync(); await Task.WhenAll( acceptTask, client.ConnectAsync(new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)listen.LocalEndPoint).Port))); using (Socket server = await acceptTask) using (var receiveSaea = new SocketAsyncEventArgs()) { if (suppressed) { ExecutionContext.SuppressFlow(); } var local = new AsyncLocal <int>(); local.Value = 42; int threadId = Environment.CurrentManagedThreadId; var mres = new ManualResetEventSlim(); receiveSaea.SetBuffer(new byte[1], 0, 1); receiveSaea.Completed += delegate { Assert.NotEqual(threadId, Environment.CurrentManagedThreadId); Assert.Equal(suppressed ? 0 : 42, local.Value); mres.Set(); }; Assert.True(client.ReceiveAsync(receiveSaea)); server.Send(new byte[1]); mres.Wait(); } } }
public static void CaptureThenSuppressThenRunFlowTest() { ThreadTestHelpers.RunTestInBackgroundThread(() => { var asyncLocal = new AsyncLocal<int>(); asyncLocal.Value = 1; ExecutionContext executionContext = ExecutionContext.Capture(); ExecutionContext.SuppressFlow(); ExecutionContext.Run( executionContext, state => { Assert.Equal(1, asyncLocal.Value); VerifyExecutionContextFlow(asyncLocal, 1); }, null); Assert.Equal(1, asyncLocal.Value); VerifyExecutionContextFlow(asyncLocal, 0); ExecutionContext.RestoreFlow(); VerifyExecutionContextFlow(asyncLocal, 1); executionContext = ExecutionContext.Capture(); asyncLocal.Value = 2; ExecutionContext.SuppressFlow(); Assert.True(ExecutionContext.IsFlowSuppressed()); ExecutionContext.Run( executionContext, state => { Assert.Equal(1, asyncLocal.Value); VerifyExecutionContextFlow(asyncLocal, 1); }, null); Assert.Equal(2, asyncLocal.Value); VerifyExecutionContextFlow(asyncLocal, 0); ExecutionContext.RestoreFlow(); VerifyExecutionContextFlow(asyncLocal, 2); }); }
public static void AsyncFlowControlTest() { ThreadTestHelpers.RunTestInBackgroundThread(() => { Action<AsyncFlowControl, AsyncFlowControl, bool> verifyEquality = (afc0, afc1, areExpectedToBeEqual) => { Assert.Equal(areExpectedToBeEqual, afc0.Equals(afc1)); Assert.Equal(areExpectedToBeEqual, afc0.Equals((object)afc1)); Assert.Equal(areExpectedToBeEqual, afc0 == afc1); Assert.NotEqual(areExpectedToBeEqual, afc0 != afc1); }; AsyncFlowControl asyncFlowControl0 = ExecutionContext.SuppressFlow(); ExecutionContext.RestoreFlow(); AsyncFlowControl asyncFlowControl1 = ExecutionContext.SuppressFlow(); ExecutionContext.RestoreFlow(); verifyEquality(asyncFlowControl0, asyncFlowControl1, true); verifyEquality(asyncFlowControl1, asyncFlowControl0, true); var asyncLocal = new AsyncLocal<int>(); asyncLocal.Value = 1; asyncFlowControl1 = ExecutionContext.SuppressFlow(); ExecutionContext.RestoreFlow(); verifyEquality(asyncFlowControl0, asyncFlowControl1, true); verifyEquality(asyncFlowControl1, asyncFlowControl0, true); asyncFlowControl1 = new AsyncFlowControl(); verifyEquality(asyncFlowControl0, asyncFlowControl1, false); verifyEquality(asyncFlowControl1, asyncFlowControl0, false); ThreadTestHelpers.RunTestInBackgroundThread(() => asyncFlowControl1 = ExecutionContext.SuppressFlow()); verifyEquality(asyncFlowControl0, asyncFlowControl1, false); verifyEquality(asyncFlowControl1, asyncFlowControl0, false); }); }
public static void FlowTest() { ThreadTestHelpers.RunTestInBackgroundThread(() => { var asyncLocal = new AsyncLocal<int>(); asyncLocal.Value = 1; var asyncFlowControl = default(AsyncFlowControl); Action<Action, Action> verifySuppressRestore = (suppressFlow, restoreFlow) => { VerifyExecutionContextFlow(asyncLocal, 1); ExecutionContext executionContext2 = ExecutionContext.Capture(); suppressFlow(); VerifyExecutionContextFlow(asyncLocal, 0); VerifyExecutionContext(executionContext2, asyncLocal, 1); executionContext2 = ExecutionContext.Capture(); restoreFlow(); VerifyExecutionContextFlow(asyncLocal, 1); VerifyExecutionContext(executionContext2, asyncLocal, 0); }; verifySuppressRestore( () => asyncFlowControl = ExecutionContext.SuppressFlow(), () => asyncFlowControl.Undo()); verifySuppressRestore( () => asyncFlowControl = ExecutionContext.SuppressFlow(), () => asyncFlowControl.Dispose()); verifySuppressRestore( () => ExecutionContext.SuppressFlow(), () => ExecutionContext.RestoreFlow()); Assert.Throws<InvalidOperationException>(() => ExecutionContext.RestoreFlow()); asyncFlowControl = ExecutionContext.SuppressFlow(); Assert.Throws<InvalidOperationException>(() => ExecutionContext.SuppressFlow()); ThreadTestHelpers.RunTestInBackgroundThread(() => { ExecutionContext.SuppressFlow(); Assert.Throws<InvalidOperationException>(() => asyncFlowControl.Undo()); Assert.Throws<InvalidOperationException>(() => asyncFlowControl.Dispose()); ExecutionContext.RestoreFlow(); }); asyncFlowControl.Undo(); Assert.Throws<InvalidOperationException>(() => asyncFlowControl.Undo()); Assert.Throws<InvalidOperationException>(() => asyncFlowControl.Dispose()); // Changing an async local value does not prevent undoing a flow-suppressed execution context. In .NET Core, the // execution context is immutable, so changing an async local value changes the execution context instance, // contrary to the desktop framework. asyncFlowControl = ExecutionContext.SuppressFlow(); asyncLocal.Value = 2; asyncFlowControl.Undo(); VerifyExecutionContextFlow(asyncLocal, 2); asyncFlowControl = ExecutionContext.SuppressFlow(); asyncLocal.Value = 3; asyncFlowControl.Dispose(); VerifyExecutionContextFlow(asyncLocal, 3); ExecutionContext.SuppressFlow(); asyncLocal.Value = 4; ExecutionContext.RestoreFlow(); VerifyExecutionContextFlow(asyncLocal, 4); // An async flow control cannot be undone when a different execution context is applied. The desktop framework // mutates the execution context when its state changes, and only changes the instance when an execution context // is applied (for instance, through ExecutionContext.Run). The framework prevents a suppressed-flow execution // context from being applied by returning null from ExecutionContext.Capture, so the only type of execution // context that can be applied is one whose flow is not suppressed. After suppressing flow and changing an async // local's value, the desktop framework verifies that a different execution context has not been applied by // checking the execution context instance against the one saved from when flow was suppressed. In .NET Core, // since the execution context instance will change after changing the async local's value, it verifies that a // different execution context has not been applied, by instead ensuring that the current execution context's // flow is suppressed. { ExecutionContext executionContext = null; Action verifyCannotUndoAsyncFlowControlAfterChangingExecutionContext = () => { ExecutionContext.Run( executionContext, state => { Assert.Throws<InvalidOperationException>(() => asyncFlowControl.Undo()); Assert.Throws<InvalidOperationException>(() => asyncFlowControl.Dispose()); }, null); }; executionContext = ExecutionContext.Capture(); asyncFlowControl = ExecutionContext.SuppressFlow(); verifyCannotUndoAsyncFlowControlAfterChangingExecutionContext(); asyncFlowControl.Undo(); executionContext = ExecutionContext.Capture(); asyncFlowControl = ExecutionContext.SuppressFlow(); asyncLocal.Value = 5; verifyCannotUndoAsyncFlowControlAfterChangingExecutionContext(); asyncFlowControl.Undo(); VerifyExecutionContextFlow(asyncLocal, 5); } }); }
public static void CreateCopyTest() { ThreadTestHelpers.RunTestInBackgroundThread(() => { var asyncLocal = new AsyncLocal<int>(); ExecutionContext executionContext = ExecutionContext.Capture(); VerifyExecutionContext(executionContext, asyncLocal, 0); executionContext = ExecutionContext.Capture(); ExecutionContext executionContextCopy0 = executionContext.CreateCopy(); asyncLocal.Value = 1; executionContext = ExecutionContext.Capture(); VerifyExecutionContext(executionContext, asyncLocal, 1); VerifyExecutionContext(executionContextCopy0, asyncLocal, 0); executionContext = ExecutionContext.Capture(); ExecutionContext executionContextCopy1 = executionContext.CreateCopy(); VerifyExecutionContext(executionContextCopy1, asyncLocal, 1); }); }
private void ApplicationControl_Load(object sender, System.EventArgs e) { Console.WriteLine("enter ApplicationControl_Load " + new { Thread.CurrentThread.ManagedThreadId }); this.SpecialEvent += value => { Console.WriteLine("SpecialEvent " + new { value, Thread.CurrentThread.ManagedThreadId }); }; IProgress<string> progress = new Progress<string>( handler: value => { Console.WriteLine("Progress " + new { value, Thread.CurrentThread.ManagedThreadId }); } ); progress.Report("hello from UI"); var loc1 = new AsyncLocal<string>( // would we be able to send the delegate over to worker? // called by ExecutionContext //> TestAsyncLocal.exe!TestAsyncLocal.ApplicationControl.ApplicationControl_Load.AnonymousMethod__1_1(System.Threading.AsyncLocalValueChangedArgs<string> value) Line 40 C# // mscorlib.dll!System.Threading.AsyncLocal<T>.System.Threading.IAsyncLocal.OnValueChanged(object previousValueObj, object currentValueObj, bool contextChanged) Unknown // mscorlib.dll!System.Threading.ExecutionContext.OnAsyncLocalContextChanged(System.Threading.ExecutionContext previous, System.Threading.ExecutionContext current) Unknown // mscorlib.dll!System.Threading.ExecutionContext.SetExecutionContext(System.Threading.ExecutionContext executionContext, bool preserveSyncCtx) Unknown // mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown // mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown // mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task currentTaskSlot) Unknown // mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) Unknown // mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Unknown // mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() Unknown // mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Unknown valueChangedHandler: value => { Console.WriteLine("AsyncLocal " + new { value.ThreadContextChanged, value.CurrentValue, value.PreviousValue, Thread.CurrentThread.ManagedThreadId }); } ); loc1.Value = "hello from UI"; var s = new SemaphoreSlim(1); this.SpecialEvent("hello from UI"); Task.Run( delegate { Console.WriteLine("enter worker " + new { loc1, progress, Thread.CurrentThread.ManagedThreadId }); //this.InvokeRequired this.SpecialEvent("hello from UI " + new { this.InvokeRequired }); progress.Report("hello from worker"); s.Release(); loc1.Value = "hello from worker / " + new { loc1.Value }; } ); //enter ApplicationControl_Load { ManagedThreadId = 3 } //AsyncLocal { ThreadContextChanged = False, CurrentValue = hello from UI, PreviousValue = , ManagedThreadId = 3 } //SpecialEvent { value = hello from UI, ManagedThreadId = 3 } //ApplicationForm.Load //AsyncLocal { ThreadContextChanged = True, CurrentValue = hello from UI, PreviousValue = , ManagedThreadId = 5 } //AsyncLocal { ThreadContextChanged = True, CurrentValue = hello from UI, PreviousValue = , ManagedThreadId = 4 } //SemaphoreSlim WaitAsync { CurrentCount = 0, ManagedThreadId = 5 } //AsyncLocal { ThreadContextChanged = True, CurrentValue = , PreviousValue = hello from UI, ManagedThreadId = 5 } //enter worker { loc1 = System.Threading.AsyncLocal`1[System.String], progress = System.Progress`1[System.String], ManagedThreadId = 4 } //SpecialEvent { value = hello from UI { InvokeRequired = True }, ManagedThreadId = 4 } //AsyncLocal { ThreadContextChanged = False, CurrentValue = hello from worker / { Value = hello from UI }, PreviousValue = hello from UI, ManagedThreadId = 4 } //AsyncLocal { ThreadContextChanged = True, CurrentValue = , PreviousValue = hello from worker / { Value = hello from UI }, ManagedThreadId = 4 } //AsyncLocal { ThreadContextChanged = True, CurrentValue = , PreviousValue = hello from UI, ManagedThreadId = 3 } //Progress { value = hello from UI, ManagedThreadId = 3 } //AsyncLocal { ThreadContextChanged = True, CurrentValue = hello from UI, PreviousValue = , ManagedThreadId = 3 } //Progress { value = hello from worker, ManagedThreadId = 3 } s.WaitAsync().ContinueWith( t => { Console.WriteLine("SemaphoreSlim WaitAsync " + new { s.CurrentCount, Thread.CurrentThread.ManagedThreadId }); } ); }
public static async Task AddUpdateAndRemoveManyLocals_ReferenceType() { var locals = new AsyncLocal<string>[40]; for (int i = 0; i < locals.Length; i++) { locals[i] = new AsyncLocal<string>(); locals[i].Value = i.ToString(); for (int j = 0; j <= i; j++) { Assert.Equal(j.ToString(), locals[j].Value); locals[j].Value = (j + 1).ToString(); Assert.Equal((j + 1).ToString(), locals[j].Value); locals[j].Value = j.ToString(); Assert.Equal(j.ToString(), locals[j].Value); } } for (int i = 0; i < locals.Length; i++) { locals[i].Value = null; Assert.Null(locals[i].Value); for (int j = i + 1; j < locals.Length; j++) { Assert.Equal(j.ToString(), locals[j].Value); } } }
public static IDisposable OpenScope(ErpUser user) { if (current == null) { current = new AsyncLocal<SecurityContext>(); current.Value = new SecurityContext(); } if (current.Value == null) current.Value = new SecurityContext(); current.Value.userStack.Push(user); return current.Value; }
private static void VerifyExecutionContextFlow(AsyncLocal<int> asyncLocal, int expectedValue) { Assert.Equal(expectedValue == 0, ExecutionContext.IsFlowSuppressed()); if (ExecutionContext.IsFlowSuppressed()) { Assert.Null(ExecutionContext.Capture()); } VerifyExecutionContext(ExecutionContext.Capture(), asyncLocal, expectedValue); int asyncLocalValue = -1; var done = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem( state => { asyncLocalValue = asyncLocal.Value; done.Set(); }); done.CheckedWait(); Assert.Equal(expectedValue, asyncLocalValue); }
public static async Task AsyncMethodNotifications() { // // Define thread-local and async-local values. The async-local value uses its notification // to keep the thread-local value in sync with the async-local value. // ThreadLocal<int> tls = new ThreadLocal<int>(); AsyncLocal<int> als = new AsyncLocal<int>(args => { tls.Value = args.CurrentValue; }); Assert.Equal(tls.Value, als.Value); als.Value = 1; Assert.Equal(tls.Value, als.Value); als.Value = 2; Assert.Equal(tls.Value, als.Value); await Run(async () => { Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 2); als.Value = 3; Assert.Equal(tls.Value, als.Value); Task t = Run(async () => { Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 3); als.Value = 4; Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 4); await Task.Run(() => { Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 4); als.Value = 5; Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 5); }); Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 4); als.Value = 6; Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 6); }); Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 3); await Task.Yield(); Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 3); await t; Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 3); }); Assert.Equal(tls.Value, als.Value); Assert.Equal(als.Value, 2); }
public static async Task SetValueFromNotification() { int valueToSet = 0; AsyncLocal<int> local = null; local = new AsyncLocal<int>(args => { if (args.ThreadContextChanged) local.Value = valueToSet; }); valueToSet = 2; local.Value = 1; Assert.Equal(local.Value, 1); await Run(async () => { local.Value = 3; valueToSet = 4; }); Assert.Equal(local.Value, 4); }
public static async Task ExecutionContextCopyOnWrite() { AsyncLocal<int> local = new AsyncLocal<int>(); local.Value = 42; await Run(async () => { SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); Assert.Equal(42, local.Value); local.Value = 12; }); Assert.Equal(local.Value, 42); }
public static async Task NotifyOnValuePropertyChange() { bool expectThreadContextChange = false; int expectedPreviousValue = 0; int expectedCurrentValue = 1; bool gotNotification = false; bool expectNotification = false; AsyncLocal<int> local = new AsyncLocal<int>( args => { gotNotification = true; Assert.True(expectNotification); expectNotification = false; Assert.Equal(args.ThreadContextChanged, expectThreadContextChange); Assert.Equal(args.PreviousValue, expectedPreviousValue); Assert.Equal(args.CurrentValue, expectedCurrentValue); }); expectNotification = true; local.Value = 1; Assert.True(gotNotification); expectNotification = true; expectThreadContextChange = true; expectedPreviousValue = local.Value; expectedCurrentValue = 0; return; }
public void Start_ExecutionContextChangesInMoveNextDontFlowOut() { var al = new AsyncLocal<int> { Value = 0 }; int calls = 0; var dsm = new DelegateStateMachine { MoveNextDelegate = () => { al.Value++; calls++; } }; dsm.MoveNext(); Assert.Equal(1, al.Value); Assert.Equal(1, calls); dsm.MoveNext(); Assert.Equal(2, al.Value); Assert.Equal(2, calls); AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder(); b.Start(ref dsm); Assert.Equal(2, al.Value); // change should not be visible Assert.Equal(3, calls); // Make sure we've not caused the Task to be allocated b.SetResult(42); ValueTask<int> vt = b.Task; Assert.NotSame(vt.AsTask(), vt.AsTask()); }
public static void QueueRegisterPositiveAndFlowTest() { var asyncLocal = new AsyncLocal<int>(); asyncLocal.Value = 1; var obj = new object(); var registerWaitEvent = new AutoResetEvent(false); var threadDone = new AutoResetEvent(false); RegisteredWaitHandle registeredWaitHandle = null; Exception backgroundEx = null; int backgroundAsyncLocalValue = 0; Action<bool, Action> commonBackgroundTest = (isRegisteredWaitCallback, test) => { try { if (isRegisteredWaitCallback) { RegisteredWaitHandle toUnregister = registeredWaitHandle; registeredWaitHandle = null; Assert.True(toUnregister.Unregister(threadDone)); } test(); backgroundAsyncLocalValue = asyncLocal.Value; } catch (Exception ex) { backgroundEx = ex; } finally { if (!isRegisteredWaitCallback) { threadDone.Set(); } } }; Action<bool> waitForBackgroundWork = isWaitForRegisteredWaitCallback => { if (isWaitForRegisteredWaitCallback) { registerWaitEvent.Set(); } threadDone.CheckedWait(); if (backgroundEx != null) { throw new AggregateException(backgroundEx); } }; ThreadPool.QueueUserWorkItem( state => { commonBackgroundTest(false, () => { Assert.Same(obj, state); }); }, obj); waitForBackgroundWork(false); Assert.Equal(1, backgroundAsyncLocalValue); ThreadPool.UnsafeQueueUserWorkItem( state => { commonBackgroundTest(false, () => { Assert.Same(obj, state); }); }, obj); waitForBackgroundWork(false); Assert.Equal(0, backgroundAsyncLocalValue); registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject( registerWaitEvent, (state, timedOut) => { commonBackgroundTest(true, () => { Assert.Same(obj, state); Assert.False(timedOut); }); }, obj, UnexpectedTimeoutMilliseconds, false); waitForBackgroundWork(true); Assert.Equal(1, backgroundAsyncLocalValue); registeredWaitHandle = ThreadPool.UnsafeRegisterWaitForSingleObject( registerWaitEvent, (state, timedOut) => { commonBackgroundTest(true, () => { Assert.Same(obj, state); Assert.False(timedOut); }); }, obj, UnexpectedTimeoutMilliseconds, false); waitForBackgroundWork(true); Assert.Equal(0, backgroundAsyncLocalValue); }
public unsafe void FlowsAsyncLocalsToCallback() { // Makes sure that we flow async locals to callback const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(@"AsyncLocal.tmp"); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext context = new OverlappedContext(); byte[] data = new byte[DATA_SIZE]; AsyncLocal<int> asyncLocal = new AsyncLocal<int>(); asyncLocal.Value = 10; int? result = null; IOCompletionCallback callback = (_, __, ___) => { result = asyncLocal.Value; OnOverlappedOperationCompleted(_, __, ___); }; NativeOverlapped* overlapped = boundHandle.AllocateNativeOverlapped(callback, context, data); fixed (byte* p = data) { int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Wait for overlapped operation to complete context.Event.WaitOne(); } boundHandle.FreeNativeOverlapped(overlapped); boundHandle.Dispose(); handle.Dispose(); Assert.Equal(10, result); }
public static void SerializationTest() { ThreadTestHelpers.RunTestInBackgroundThread(() => { var asyncLocal = new AsyncLocal<int>(); asyncLocal.Value = 1; ExecutionContext executionContext = ExecutionContext.Capture(); VerifyExecutionContext(executionContext, asyncLocal, 1); Assert.Throws<ArgumentNullException>(() => executionContext.GetObjectData(null, new StreamingContext())); var binaryFormatter = new BinaryFormatter(); var memoryStream = new MemoryStream(); binaryFormatter.Serialize(memoryStream, executionContext); memoryStream.Close(); byte[] binaryData = memoryStream.ToArray(); memoryStream = new MemoryStream(binaryData); executionContext = (ExecutionContext)binaryFormatter.Deserialize(memoryStream); memoryStream.Close(); }); }
private static void VerifyExecutionContext( ExecutionContext executionContext, AsyncLocal<int> asyncLocal, int expectedValue) { int actualValue = 0; Action run = () => ExecutionContext.Run(executionContext, state => actualValue = asyncLocal.Value, null); if (executionContext == null) { Assert.Throws<InvalidOperationException>(() => run()); } else { run(); } Assert.Equal(expectedValue, actualValue); }
public static async Task NotifyOnThreadContextChangeWithOneEmptyContext() { bool expectThreadContextChange = false; int expectedPreviousValue = 0; int expectedCurrentValue = 1; bool gotNotification = false; bool expectNotification = false; AsyncLocal<int> local = new AsyncLocal<int>( args => { gotNotification = true; Assert.True(expectNotification); expectNotification = false; Assert.Equal(args.ThreadContextChanged, expectThreadContextChange); Assert.Equal(args.PreviousValue, expectedPreviousValue); Assert.Equal(args.CurrentValue, expectedCurrentValue); }); ExecutionContext ec = ExecutionContext.Capture(); expectNotification = true; expectedPreviousValue = 0; expectedCurrentValue = 1; local.Value = 1; Assert.True(gotNotification); gotNotification = false; expectNotification = true; expectedPreviousValue = 1; expectedCurrentValue = 0; expectThreadContextChange = true; ExecutionContext.Run( ec, _ => { Assert.True(gotNotification); gotNotification = false; Assert.Equal(local.Value, 0); expectNotification = true; expectedPreviousValue = 0; expectedCurrentValue = 1; expectThreadContextChange = true; return; }, null); Assert.True(gotNotification); gotNotification = false; Assert.Equal(local.Value, 1); expectNotification = true; expectThreadContextChange = true; expectedPreviousValue = local.Value; expectedCurrentValue = 0; return; }
public void Enable() { if (m_current == null) { m_current = new AsyncLocal<ActivityInfo>(ActivityChanging); } }
public void Enable() { if (m_current == null) { EventSource.OutputDebugString("Enabling Activity Tracking"); m_current = new AsyncLocal<ActivityInfo>(ActivityChanging); } }
public static async Task AddAndUpdateManyLocals_ValueType() { var locals = new AsyncLocal<int>[40]; for (int i = 0; i < locals.Length; i++) { locals[i] = new AsyncLocal<int>(); locals[i].Value = i; for (int j = 0; j <= i; j++) { Assert.Equal(j, locals[j].Value); locals[j].Value = j + 1; Assert.Equal(j + 1, locals[j].Value); locals[j].Value = j; Assert.Equal(j, locals[j].Value); } } }
internal AsyncLocalStackWrapper(AsyncLocal<StackNode> stack) { Debug.Assert(stack != null); _stack = stack; }