Ejemplo n.º 1
0
            public SingleThreadSyncContext(SingleThreadApartment apartment, bool pumpMessages = true)
            {
                _apartment    = apartment;
                _pumpMessages = pumpMessages;

                if (_pumpMessages)
                {
                    base.SetWaitNotificationRequired();
                }

                var startTcs = new TaskCompletionSource <TaskScheduler>();

                void threadStart()
                {
                    try
                    {
                        SynchronizationContext.SetSynchronizationContext(this);
                        startTcs.TrySetResult(TaskScheduler.FromCurrentSynchronizationContext());
                        try
                        {
                            foreach ((SendOrPostCallback d, object?state) in _items.GetConsumingEnumerable())
                            {
                                try
                                {
                                    d(state);
                                }
                                catch (Exception ex)
                                {
                                    _apartment.AddException(ex);
                                }
                                finally
                                {
                                    OperationCompleted();
                                }
                            }
                        }
                        finally
                        {
                            SynchronizationContext.SetSynchronizationContext(null);
                            _apartment.TrySetCompletion();
                        }
                    }
                    catch (Exception ex)
                    {
                        if (!startTcs.TrySetException(ex))
                        {
                            throw;
                        }
                    }
                }

                _thread = new Thread(threadStart);
                _thread.SetApartmentState(ApartmentState.STA);
                _thread.IsBackground = true;
                _thread.Start();

                this.TaskScheduler = startTcs.Task.Result;
            }
Ejemplo n.º 2
0
        public async Task Test_async_void_exceptions_are_captured()
        {
            await using var apartment = new SingleThreadApartment();
            await apartment.Run(async() =>
            {
                await Task.Yield();

                Assert.IsTrue(SynchronizationContext.Current is SingleThreadApartment.SingleThreadSyncContext);

                async void AsyncVoidMethod0()
                {
                    await Task.Delay(400);
                    throw new InvalidOperationException();
                }

                async void AsyncVoidMethod1()
                {
                    await Task.Delay(600);
                    throw new NotSupportedException();
                }

                AsyncVoidMethod0();
                AsyncVoidMethod1();
            });

            apartment.Complete();

            try
            {
                await apartment.Completion.WithAggregatedExceptions();

                Assert.Fail("Must not reach here, expecting exceptions.");
            }
            catch (AssertFailedException)
            {
                throw;
            }
            catch (Exception ex)
            {
                apartment.ClearExceptions();

                // we expect to see 2 exceptions wrapped as AggregateException
                Assert.IsTrue(apartment.AnyBackgroundOperation == false);

                var aggregate = ex as AggregateException;
                Assert.IsNotNull(aggregate);
                Assert.IsTrue(aggregate !.InnerExceptions.Count == 2);
                Assert.IsTrue(aggregate.InnerExceptions[0] is InvalidOperationException);
                Assert.IsTrue(aggregate.InnerExceptions[1] is NotSupportedException);
            }
        }