首页 > 解决方案 > 如何等待方法完成然后执行新操作?

问题描述

我正在设置我的架构以使用 Cef.Offscreen。为了便于使用,我划分了一些部分。但是我遇到了一个问题,即控制器加载完成并在所有内容都能够加载之前提供视图。

这是我的结构->控制器

public ActionResult InitBrowser()
    {

        ICefSharpRenderer renderer = RendererSingelton.GetInstance();
        //Try to render something in default appdomain
        renderer.LoginToTradingView(null, null);

        ViewBag.SiteTitle = BrowserActions.RunScriptInNamedBrowser("loginbrowser", @"(function() {return document.title;} )();");

        ViewBag.ImagesixtyfourUrl = BrowserActions.TakeScreenshot("loginbrowser");

        //this is returned to fast, we have to wait for all

        return View(); 
    }

我有这个类来做一些基本的动作并在需要时进行初始化。

public class CefSharpRenderer : MarshalByRefObject, ICefSharpRenderer
{
    private ChromiumWebBrowser _browser;
    private TaskCompletionSource<JavascriptResponse> _taskCompletionSource;
    private string _name;

    public void LoginToTradingView(string url, string browserName)
    {
        CheckIfCefIsInitialized();
        BrowserFactory.GetBrowserInstance(@"https://se.tradingview.com/", "loginbrowser");

    }


   public void CreateBrowserAndGoToUrl(string url, string browserName)
   {
        CheckIfCefIsInitialized();
        BrowserFactory.GetBrowserInstance(url, "browserName");

    }

    public void CheckIfCefIsInitialized()
    {
        if (!Cef.IsInitialized)
        {
            var settings = new CefSettings();
            var assemblyPath = Path.GetDirectoryName(new Uri(GetType().Assembly.CodeBase).LocalPath);

            settings.BrowserSubprocessPath = Path.Combine(assemblyPath, "CefSharp.BrowserSubprocess.exe");
            settings.ResourcesDirPath = assemblyPath;
            settings.LocalesDirPath = Path.Combine(assemblyPath, "locales");

            var osVersion = Environment.OSVersion;
            //Disable GPU for Windows 7
            if (osVersion.Version.Major == 6 && osVersion.Version.Minor == 1)
            {
                // Disable GPU in WPF and Offscreen examples until #1634 has been resolved
                settings.CefCommandLineArgs.Add("disable-gpu", "1");
            }

            //Perform dependency check to make sure all relevant resources are in our output directory.
            Cef.Initialize(settings, performDependencyCheck: false, cefApp: null);
        }
    }

}

我在这里得到了我的浏览器实例并连接了要触发的事件。

public static class BrowserFactory
{

    public static ChromiumWebBrowser GetBrowserInstance(string _url, string browsername)
    {
        if (!BrowserContainer.CheckIfBrowserExists(browsername))
        {
            ChromiumWebBrowser _browser = new ChromiumWebBrowser(_url);
            _browser.LoadingStateChanged += BrowserEvents.OnLoadingStateChanged;
            BrowserContainer.AddDataHolder(browsername, new DataBrowserHolder { BrowserName = browsername, ChromiumWebBrow = _browser });

            return _browser;
        }

        return null;

    }
}

Browserevent 加载正确的页面。

    public static class BrowserEvents
{
    public static void OnLoadingStateChanged(object sender, LoadingStateChangedEventArgs args)
    {
        if (args.IsLoading == false)
        {
            ChromiumWebBrowser cwb = (ChromiumWebBrowser)sender;

            if (cwb.Address == "https://se.tradingview.com/")
            {
                BrowserActions.LogInToTradingView("xxxxx", "yyyyyyy", "loginbrowser");
            }
        }
    }
}

最后我的浏览器操作,线程休眠的备用医疗它正在建设中,它可以在 atm 工作。

  public static class BrowserActions
{
    public static void LogInToTradingView(string twusername, string twpassword, string browserName)
    {
        ChromiumWebBrowser _dataholder = BrowserContainer.GetDataHolderByName(browserName).ChromiumWebBrow;

        IFrame ifww = _dataholder.GetMainFrame();
        //    var lull = @"(function() { var serielength = TradingView.bottomWidgetBar._widgets.backtesting._reportWidgetsSet.reportWidget._data.filledOrders.length; return serielength; })();";
        //    JavascriptResponse _js = Task.Run(async () => { return await _browser.GetMainFrame().EvaluateScriptAsync(lull); }).Result;

        ifww.ExecuteJavaScriptAsync(@"(function() { window.document.getElementsByClassName('tv-header__link tv-header__link--signin js-header__signin')[0].click();})();");

        //  var loginusernamescript =  
        var loginpasswordscript = @"(function() { window.document.getElementsByClassName('tv-control-material-input tv-signin-dialog__input tv-control-material-input__control')[1].value= " + twpassword + "; })();";
        var clkloginbtn = @"(function() { document.getElementsByClassName('tv-button tv-button--no-border-radius tv-button--size_large tv-button--primary_ghost tv-button--loader')[0].click();})();";
        Thread.Sleep(300);
        ifww.ExecuteJavaScriptAsync(@"(function() { window.document.getElementsByClassName('tv-control-material-input tv-signin-dialog__input tv-control-material-input__control')[0].click();})();");
        Thread.Sleep(50);
        ifww.ExecuteJavaScriptAsync(@"(function() { window.document.getElementsByClassName('tv-control-material-input tv-signin-dialog__input tv-control-material-input__control')[0].value = '" + twusername + "';})();");
        Thread.Sleep(50);
        ifww.ExecuteJavaScriptAsync(@"(function() { window.document.getElementsByClassName('tv-control-material-input tv-signin-dialog__input tv-control-material-input__control')[1].click();})();");
        Thread.Sleep(50);
        ifww.ExecuteJavaScriptAsync(@"(function() { window.document.getElementsByClassName('tv-control-material-input tv-signin-dialog__input tv-control-material-input__control')[1].value = '" + twpassword + "';})();");
        Thread.Sleep(50);
        ifww.ExecuteJavaScriptAsync(@"(function() { document.getElementsByClassName('tv-button tv-button--no-border-radius tv-button--size_large tv-button--primary_ghost tv-button--loader')[0].click();})();");

    }

    public static string TakeScreenshot(string browserName)
    {
        try
        {
            Bitmap img = Task.Run(async () => { return await BrowserContainer.GetDataHolderByName(browserName).ChromiumWebBrow.ScreenshotAsync(); }).Result;
            //    object mgss = img.Clone();
            string baseen = ExtraFunctions.ToBase64String(img, ImageFormat.Png);
            return baseen;
        }
        catch (Exception e)
        {
            var x = e.InnerException;
            return null;
        }
    }

    public static string RunScriptInNamedBrowser(string browserName, string script)
    {
        try
        {
            string str = Task.Run(async () => { return await BrowserContainer.GetDataHolderByName(browserName).ChromiumWebBrow.GetMainFrame().EvaluateScriptAsync(script); }).Result.ToString();
            //    object mgss = img.Clone();
            return str;
        }
        catch (Exception e)
        {
            var x = e.InnerException;
            return null;
        }
    }
}

如何让我的浏览器操作向我的控制器报告,以便我可以等待它们完成?

标签: c#asynchronousasp.net-mvc-5async-await

解决方案


对于Task要返回报告的异步操作,可以使用Progress<T>. 在异步 API中启用进度和取消详细介绍了如何完成。关键是:

var progressIndicator = new Progress<int>(ReportProgress);

这将创建一个Progress<T>对象,该对象可以指示任务完成的程度,还可以按(ReportProgress)设定的时间间隔调用自定义方法。如果需要,您可以创建自定义类,而不是使用int.

因此,您的浏览器操作可以使用进度报告方法向控制器报告,直到一切完成。


推荐阅读