chromelyapps / Chromely

Build Cross Platform HTML Desktop Apps on .NET using native GUI, HTML5, JavaScript, CSS, Owin, AspNetCore (MVC, RazorPages, Blazor)
MIT License
2.98k stars 279 forks source link

On CefGlue child process launch arguments called multiple time #283

Closed redplane closed 3 years ago

redplane commented 3 years ago

I'm using Chromely for my application, the implementation is below:

public class XLinkApp : ChromelyBasicApp
    {
        #region Properties

        private readonly IConfiguration _configuration;

        #endregion

        #region Constructor

        public XLinkApp(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        #endregion

        #region Methods

        public override void ConfigureServices(IServiceCollection services)
        {
            // Service registration....
        }

        public override void Initialize(IServiceProvider serviceProvider)
        {
            var logger = serviceProvider.GetService<ILogger>();
            // Update the new content first.
            logger.Debug($"Calling {nameof(UpdateNewContentVersionAsync)}");
            UpdateNewContentVersionAsync(serviceProvider).Wait();

            base.Initialize(serviceProvider);
        }

        #endregion

        #region Internal methods

        /// <summary>
        ///     Check whether new application is available or not.
        ///     If available, download the content.
        /// </summary>
        /// <returns></returns>
        protected virtual async Task UpdateNewContentVersionAsync(IServiceProvider serviceProvider)
        {
            // Check for new version ....
        }

        #endregion
    }

As I understand, ConfigureServices, Initialize will only run once when the application start. However, by taking a look at the message on the console, I noticed:

This is annoying because I have some services which are registered as Singleton, one of them is to manage Serial Port connection.

Because of calling multiple Initialize, ConfigureServices, my service access to Serial Port multiple time -> the second one will be prevented from accessing COM Port (due to its busy state).

Is it a bug of CefSharp ? Any solution for this ?

mattkol commented 3 years ago

@redplane

Is it a bug of CefSharp ?

Is this about CefGlue or CefSharp? I am assuming CefGlue.

If you will be making lots of advanced changes, I will suggest that you spend sometime understanding CEF process generally, specifically CEF architecture - http://www.chromium.org/developers/design-documents/multi-process-architecture

CEF is multi-process, so yes, what you write in the Program Main method will run for every process. To stop that running for every process, you need sub-process - https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage#markdown-header-separate-sub-process-executable

CefSharp has sub-process implemented, CefGlue does not. Chromely used to have sub-process implemented for Windows but since a change in CEF Network Service, that has been discontinued.

A workaround with what you are trying to do is to check for the process running and ensure the method you want invoked is done only for that process. This issue will help - https://github.com/chromelyapps/Chromely/issues/213 Also -

https://github.com/chromelyapps/demo-projects/blob/5302b553770098fdc86ed38b53e080016e267602/web-chromely/web-chromely-mvc/Program.cs#L30

I will suggest:

     static void Main(string[] args)
     {
            var proctype = ClientAppUtils.GetProcessType(args);

            AppBuilder
            .Create()
            .UseApp<XLinkApp>(new XLinkApp(proctype))
            .Build()
            .Run(args);
     }

    public class XLinkApp : ChromelyBasicApp
    {
        private readonly ProcessType _processType;

        public XLinkApp(ProcessType processType)
        {
            _processType = processType;
        }

        public override void ConfigureServices(IServiceCollection services)
        {
            // Service registration....
        }

        public override void Initialize(IServiceProvider serviceProvider)
        {
            if (_processType == ProcessType.Browser)
                UpdateNewContentVersionAsync(serviceProvider).Wait();

            base.Initialize(serviceProvider);
        }
    }