从主窗体的线程调用异步方法(在子窗体内)

问题描述 投票:0回答:1

我真的很想理解并解决这个困扰我几天的问题。我读了数百个线程,但无法让它工作。

我有一个主要表单,在辅助表单上有一个 WebView2 控件。目的是从主窗体控制WebView2。它们的配置如下:

我的目标是使用主表单将一些 HTML 代码从辅助表单加载到 WebView2 中,然后对该页面进行屏幕截图。 HTML 加载部分正在工作,因此我接下来将重点关注屏幕截图问题。我使用这个方法来截图。当直接调用时它本身工作正常,但是当我从线程或后台工作者调用它时它会失败。是的,我知道,由于“跨线程调用”,这种行为是预期的。请多多包涵! 理想情况下,我认为它应该像这样工作(过于简化的代码): private void PrimaryForm_Load(...) { _secondaryForm = new SecondaryForm(); _secondaryForm.Show(); } private void Button_Click(...) { Thread thread = new Thread(HeavyWork); thread.Start(); } private void HeavyWork() { // this method will run a few hundred times Task<string> task = CaptureScreenshotAsync(); string str = task.Result; // further process the str... } private async Task<string> CaptureScreenshotAsync() { // it will throw a cross-thread exception return await _secondaryForm.webView.CoreWebView2.CallDevToolsProtocolMethodAsync("Page.captureScreenshot", "{}"); }

正如你所看到的

这里
我尝试过以几种方式调用它,但没有成功。另外,使其同步。尝试过
this

thisthat等。我无法让它正常工作。 我也尝试过像这样直接调用 HeavyWork 方法:

private void Button_Click(...) { HeavyWork(); }

但运气不好,我要么遇到跨线程异常,要么冻结。喜欢

这个
这个

我自己无意中发现的唯一“黑客”是在得到任务结果之前“睡觉”一点,如下所示: private void HeavyWork() { Task<string> task = CaptureScreenshotAsync(); Sleep(250); string str = task.Result; }

这就是

Sleep
方法:

private void Sleep(int interval) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); while (stopwatch.ElapsedMilliseconds < interval) { Application.DoEvents(); } stopwatch.Stop(); }

但这只是一个奇怪的“解决方案” - 有时它不起作用(我认为是因为拍摄屏幕截图所需的时间比等待时间更长)。 

我确信一定有一个正确的处理方法。
我将非常感谢任何帮助。谢谢!

如果您使用异步方法,则应该使每个必须处理该函数结果的函数也异步。然后,您可以简单地调用顶部异步的最后一个函数,而无需等待它。异步函数内的 Invoke 调用应该可以工作。我看不出它不起作用的原因。当您从想要其结果的函数调用异步函数时,也不要忘记等待运算符。

c# multithreading winforms asynchronous invoke
1个回答
0
投票

© www.soinside.com 2019 - 2024. All rights reserved.