2017-03-01 204 views
1

我是使用异步方法的新手,所以我认为我误解了某些东西。我有一个WinForms应用程序和一个按钮,当点击按钮时,会调用一个异步方法。这必须是异步的,因为我需要对Chromium Web浏览器控件(使用CefSharp)进行JavaScript调用。我需要确保此JavaScript已完成运行,并且在继续执行下一部分方法之前浏览器已更新。在异步方法中使用await来防止下一行代码运行

我基本上试图将整个网页捕捉到一个图像。我的方法是使用JavaScript更新页面上的滚动位置,然后使用Graphics.CopyFromScreen在每个位置截取屏幕截图。这主要起作用,但是偶尔会导致图像出现错误的网页块(例如,第一个位图重复两次)。这里是我的代码:

// Calculate screen sizes, screenshot spacing etc. 

for (int i = 0; i < screenshotCount; i++) 
{ 
    int scrollSize = i == 0 ? -PageHeight : (int)browserControlHeight; 
    string script = "(function() { window.scrollBy(0, " + scrollSize.ToString() + ") })();"; 

    await browser.EvaluateScriptAsync(script); 

    // Take screenshot, add to list of bitmaps 
} 

// Combine resulting list of bitmaps 

如果我添加以下

await Task.Delay(1000); 
的EvaluateScriptAsync()调用后

,最终的图像出来正确的每一次。我正在假设javascript正在被调用,但在截图开始前没有完成。如果是这种情况,即使增加一个延迟可能不起作用(如果JavaScript花费的时间超过一秒钟,该怎么办?)。

我误解异步/等待的方式吗?

回答

5

不,问题不在于await,问题在于EvaluateScriptAsync返回的Task在您准备继续之前被标记为已完成。只要JavaScript通知浏览器它应该滚动已经执行,而不是在浏览器在发送滚动命令后重新呈现屏幕之后标记为完成,它将被标记为完成。

+0

因此,如果我添加一个额外的行到正在执行的JavaScript只是返回true,会解决这个问题吗?假设在JavaScript中,下一行将不会运行,直到滚动完成。 – jardantuan

+1

@jardantuan第二个假设是不正确的。这首先是你问题的根源。如果这个假设是真的,那么你的代码已经可以工作了。 – Servy

+0

这是有道理的。此刻,我想我可以在javascript中添加一个支票,以查看滚动位置是否发生了变化,然后返回一些内容 - 是否可行?也有可能我错过了一个更明显的解决方法。 – jardantuan

相关问题