【发布时间】:2015-04-29 18:33:10
【问题描述】:
我有一个 WebBrowser 控件,它有 InvokeScript 方法,你应该只在 WebBrowser 加载后调用它。
所以我尝试过这样的事情:
private readonly ManualResetEventSlim browserLoaded = new ManualResetEventSlim(false);
private void BrowserLoaded(object sender, NavigationEventArgs navigationEventArgs)
{
browserLoaded.Set();
}
private async Task<object> InvokeScript(string invoke, object[] parameters = null)
{
return await Task.Factory
.StartNew(() =>
{
if (!browserLoaded.Wait(TimeSpan.FromSeconds(10)))
{
throw new Exception("Timeout for waiting browser to load.");
}
})
.ContinueWith(task => parameters == null
? browser.InvokeScript(invoke)
: browser.InvokeScript(invoke, parameters), TaskScheduler.FromCurrentSynchronizationContext());
}
对我来说它看起来不是很好,但是在异步调用时可以正常工作。 出现问题,当我尝试同步读取结果值时 - 应用程序只是挂起:
private string GetEnteredText()
{
return (string)InvokeScript("getEnteredText").Result;
}
我知道,我应该一直异步,但我想知道如何处理属性:
public override string UserText
{
get
{
return GetEnteredText();
}
set
{
SetEnteredText(value);
}
}
或者在这种情况下异步是错误的方式?
更新
属性是浏览器页面中的输入字段值和 WPF 中的视图模型之间的“粘合剂”,所以我看不出将其作为单独方法的好方法,特别是因为它是更大框架的一部分(注意覆盖它的关键字)。 加载浏览器控件后,执行逻辑不会花费很长时间,我猜不到 10 毫秒,这就是为什么在这种情况下我可以使用同步执行。而且通常浏览器控件加载速度足够快,这里延迟的唯一原因是确保在加载之前不调用 InvokeScript,而不是因为它需要很长时间或smth。
【问题讨论】:
-
如果可能的话,我会尽量避免在我的 getter 和 setter 中使用逻辑。在 getter 中使用异步方法会使事情陷入困境 - 它可能现在、一分钟或一小时等返回。为了避免您在上面描述的情况,我通常会尝试触发任何必要的逻辑 before 我需要来自 getter 的数据。您能否提供更多有关使用 UserText 属性的上下文,我会看看我是否可以弄清楚在哪里调用 SetEnteredText 方法?
-
@goobering - 我已经解释了用法。
标签: c# wpf async-await