コード例 #1
0
        /// <summary>
        /// Updates the rendered state of the specified <see cref="IComponent"/>.
        /// </summary>
        /// <param name="componentId">The identifier of the <see cref="IComponent"/> to render.</param>
        protected internal void RenderNewBatch(int componentId)
        {
            // It's very important that components' rendering logic has no side-effects, and in particular
            // components must *not* trigger Render from inside their render logic, otherwise you could
            // easily get hard-to-debug infinite loops.
            // Since rendering is currently synchronous and single-threaded, we can enforce the above by
            // checking here that no other rendering process is already underway. This also means we only
            // need a single _renderBatchBuilder instance that can be reused throughout the lifetime of
            // the Renderer instance, which also means we're not allocating on a typical render cycle.
            // In the future, if rendering becomes async, we'll need a more sophisticated system of
            // capturing successive diffs from each component and probably serializing them for the
            // interop calls instead of using shared memory.

            // Note that Monitor.TryEnter is not yet supported in Mono WASM, so using the following instead
            var renderAlreadyRunning = Interlocked.CompareExchange(ref _renderBatchLock, 1, 0) == 1;

            if (renderAlreadyRunning)
            {
                throw new InvalidOperationException("Cannot render while a render is already in progress. " +
                                                    "Render logic must not have side-effects such as manually triggering other rendering.");
            }

            try
            {
                RenderInExistingBatch(_sharedRenderBatchBuilder, componentId);
                UpdateDisplay(_sharedRenderBatchBuilder.ToBatch());
            }
            finally
            {
                _sharedRenderBatchBuilder.Clear();
                Interlocked.Exchange(ref _renderBatchLock, 0);
            }
        }
コード例 #2
0
ファイル: Renderer.cs プロジェクト: willCode2Surf/Blazor
        private void ProcessRenderQueue()
        {
            _isBatchInProgress = true;

            try
            {
                // Process render queue until empty
                while (_batchBuilder.ComponentRenderQueue.Count > 0)
                {
                    var nextToRender = _batchBuilder.ComponentRenderQueue.Dequeue();
                    RenderInExistingBatch(nextToRender);
                }

                UpdateDisplay(_batchBuilder.ToBatch());
            }
            finally
            {
                RemoveEventHandlerIds(_batchBuilder.DisposedEventHandlerIds.ToRange());
                _batchBuilder.Clear();
                _isBatchInProgress = false;
            }
        }