예제 #1
0
                private async Task ZBackgroundSendAsync(cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewRootMethod(true, nameof(cCommandPipeline), nameof(ZBackgroundSendAsync));

                    mBackgroundSendBuffer.SetTracing(lContext);

                    if (mCurrentCommand != null)
                    {
                        await ZBackgroundSendAppendDataAndMoveNextAsync(lContext).ConfigureAwait(false);
                    }

                    while (true)
                    {
                        if (mCurrentCommand == null)
                        {
                            ZBackgroundSendDequeueAndAppendTag(lContext);
                            if (mCurrentCommand == null)
                            {
                                break;
                            }

                            if (mCurrentCommand.IsAuthentication)
                            {
                                await ZBackgroundSendAppendAllTextPartsAsync(lContext).ConfigureAwait(false);

                                mCurrentCommand.WaitingForContinuationRequest = true;
                                break;
                            }
                        }

                        if (mCurrentCommand.State == eCommandState.current)
                        {
                            if (ZBackgroundSendAppendLiteralHeader())
                            {
                                mCurrentCommand.WaitingForContinuationRequest = true;
                                break;
                            }

                            await ZBackgroundSendAppendDataAndMoveNextAsync(lContext).ConfigureAwait(false);
                        }
                        else
                        {
                            ZBackgroundSendTerminateCommand(lContext);
                        }
                    }

                    await mBackgroundSendBuffer.WriteAsync(lContext).ConfigureAwait(false);
                }
예제 #2
0
            private async Task ZBackgroundTaskAsync(cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewRootMethod(nameof(cCallbackSynchroniser), nameof(ZBackgroundTaskAsync));

                while (true)
                {
                    lContext.TraceVerbose("waiting");
                    await mBackgroundReleaser.GetAwaitReleaseTask(lContext).ConfigureAwait(false);

                    mBackgroundReleaser.Reset(lContext);

                    var lSynchronizationContext = SynchronizationContext;

                    if (lSynchronizationContext == null || ReferenceEquals(SynchronizationContext.Current, lSynchronizationContext))
                    {
                        lContext.TraceVerbose("on the correct sc");
                        ZInvokeWorker(lContext);
                    }
                    else
                    {
                        if (mOutstandingPost)
                        {
                            lContext.TraceVerbose("not on the correct sc: but there is an outstanding post");
                        }
                        else
                        {
                            lContext.TraceVerbose("not on the correct sc: posting an invoke to the correct one");

                            mOutstandingPost = true;

                            // this is the reason the background task exists: if the SC doesn't implement an async post method then this could block
                            lSynchronizationContext.Post(
                                (p) =>
                            {
                                mOutstandingPost = false;
                                ZInvokeWorker(lContext);
                            },
                                null);
                        }
                    }
                }
            }
예제 #3
0
                private async Task ZBackgroundTaskAsync(cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewRootMethod(nameof(cCommandPipeline), nameof(ZBackgroundTaskAsync));

                    Task lBackgroundSendTask = null;

                    try
                    {
                        while (true)
                        {
                            mBackgroundReleaser.Reset(lContext);

                            if (lBackgroundSendTask != null && lBackgroundSendTask.IsCompleted)
                            {
                                lContext.TraceVerbose("send is complete");
                                lBackgroundSendTask.Wait(); // will throw if there was an error
                                lBackgroundSendTask.Dispose();
                                lBackgroundSendTask = null;
                            }

                            if (lBackgroundSendTask == null &&
                                ((mCurrentCommand == null && mQueuedCommands.Count > 0) ||
                                 (mCurrentCommand != null && !mCurrentCommand.IsAuthentication && !mCurrentCommand.WaitingForContinuationRequest)
                                )
                                )
                            {
                                lBackgroundSendTask = ZBackgroundSendAsync(lContext);
                            }

                            if (lBackgroundSendTask == null && mCurrentCommand == null && mActiveCommands.Count == 0)
                            {
                                var lIdleConfiguration = mIdleConfiguration;

                                cExclusiveAccess.cBlock lIdleBlockBlock = null;

                                if (mState == eState.enabled && lIdleConfiguration != null)
                                {
                                    lIdleBlockBlock = mIdleBlock.TryGetBlock(lContext);
                                }

                                if (lIdleBlockBlock != null)
                                {
                                    await ZIdleAsync(lIdleConfiguration, lContext).ConfigureAwait(false);

                                    lIdleBlockBlock.Dispose();
                                }
                                else
                                {
                                    lContext.TraceVerbose("there is nothing to do, waiting for something to change");
                                    await mBackgroundReleaser.GetAwaitReleaseTask(lContext).ConfigureAwait(false);
                                }
                            }
                            else
                            {
                                Task lBuildResponseTask      = mConnection.GetBuildResponseTask(lContext);
                                Task lBackgroundReleaserTask = mBackgroundReleaser.GetAwaitReleaseTask(lContext);

                                Task lCompleted = await mBackgroundAwaiter.AwaitAny(lBuildResponseTask, lBackgroundReleaserTask, lBackgroundSendTask).ConfigureAwait(false);

                                if (ReferenceEquals(lCompleted, lBuildResponseTask))
                                {
                                    await ZBackgroundTaskProcessResponseAsync(lContext).ConfigureAwait(false);

                                    // this check here to make sure logoff is handled correctly
                                    if (mBackgroundCancellationTokenSource.IsCancellationRequested)
                                    {
                                        lContext.TraceInformation("the pipeline is stopping as requested");
                                        mBackgroundTaskException = new cPipelineStoppedException();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    catch (cUnilateralByeException e)
                    {
                        lContext.TraceInformation("the pipeline is stopping due to a unilateral bye");
                        mBackgroundTaskException = e;
                    }
                    catch (OperationCanceledException) when(mBackgroundCancellationTokenSource.IsCancellationRequested)
                    {
                        lContext.TraceInformation("the pipeline is stopping as requested");
                        mBackgroundTaskException = new cPipelineStoppedException();
                    }
                    catch (AggregateException e)
                    {
                        lContext.TraceException("the pipeline is stopping due to an unexpected exception", e);
                        var lException = e.Flatten();
                        if (lException.InnerExceptions.Count == 1)
                        {
                            mBackgroundTaskException = new cPipelineStoppedException(lException.InnerExceptions[0], lContext);
                        }
                        else
                        {
                            mBackgroundTaskException = new cPipelineStoppedException(e, lContext);
                        }
                    }
                    catch (Exception e)
                    {
                        lContext.TraceException("the pipeline is stopping due to an unexpected exception", e);
                        mBackgroundTaskException = new cPipelineStoppedException(e, lContext);
                    }

                    // if the send is still going this will kill it
                    mConnection.Disconnect(lContext);

                    if (lBackgroundSendTask != null)
                    {
                        lContext.TraceVerbose("waiting for send to complete");
                        try { await lBackgroundSendTask.ConfigureAwait(false); }
                        catch (Exception e) { lContext.TraceException("send reported an exception at pipeline stop", e); }
                        lBackgroundSendTask.Dispose();
                    }

                    lock (mPipelineLock)
                    {
                        mState = eState.stopped;
                    }

                    foreach (var lCommand in mActiveCommands)
                    {
                        lCommand.SetException(mBackgroundTaskException, lContext);
                    }
                    if (mCurrentCommand != null)
                    {
                        mCurrentCommand.SetException(mBackgroundTaskException, lContext);
                    }
                    foreach (var lCommand in mQueuedCommands)
                    {
                        lCommand.SetException(mBackgroundTaskException, lContext);
                    }

                    mDisconnected(lContext);
                }