Awesomium.Net 用于多线程访问的包装器 class 只工作一次
Awesomium.Net wrapper class for multi-threaded access only works once
要测试此 class 请从 here 安装 Awesomium.Net sdk 并将对 Awesomium.Core.dll
的引用添加到 visual studio 项目。
我遇到的问题 class 是,它只适用于第一个实例。随后的实例不会导致在 WebView
对象上触发适当的事件,并且在以后的实例中不会返回任何结果。我已经为此苦苦挣扎了好几天,似乎无法弄清楚为什么它只能工作一次。请帮忙...
Imports Awesomium.Core
Public Class Browser
Private Shared Thread As Threading.Thread
Private Shared CoreIsRunning As Boolean = False
Dim RenderedHTML As String = ""
Dim RenderingDone As Boolean = False
Private Shared Sub AwesomiumThread()
WebCore.Initialize(New WebConfig With {.LogLevel = LogLevel.None}, False)
WebCore.Run(Sub(s, e)
CoreIsRunning = True
End Sub)
End Sub
Shared Sub DeInit()
WebCore.Shutdown()
Thread = Nothing
End Sub
Shared Sub Init()
If Not WebCore.IsInitialized And IsNothing(Thread) Then
Thread = New Threading.Thread(AddressOf AwesomiumThread)
Thread.Start()
End If
End Sub
Sub New()
Init()
End Sub
Function GetRenderedHTML(URL As String) As String
Do Until CoreIsRunning
Task.Delay(300).Wait()
Loop
WebCore.QueueWork(Sub() RenderHTML(URL))
Dim startTime As Date = Date.UtcNow
Do Until RenderingDone = True
If Date.UtcNow.Subtract(startTime).TotalSeconds >= 30 Then
'view.Dispose()
'view = Nothing
'session.Dispose()
'session = Nothing
Exit Do
End If
Task.Delay(1000).Wait()
Loop
If String.IsNullOrEmpty(RenderedHTML) Then
Throw New Exception("Rendering failed!")
End If
Return Me.RenderedHTML
End Function
Private Sub RenderHTML(URL As String)
Dim session As WebSession = WebCore.CreateWebSession(New WebPreferences With {.LoadImagesAutomatically = False, .LocalStorage = False, .Plugins = False, .RemoteFonts = False, .WebAudio = False, .CanScriptsOpenWindows = False, .DefaultEncoding = "utf-8"})
Dim view As WebView = WebCore.CreateWebView(1100, 600, session, WebViewType.Offscreen)
RenderingDone = False
AddHandler view.LoadingFrameComplete, Sub(s, e)
If e.IsMainFrame Then
Me.RenderedHTML = view.ExecuteJavascriptWithResult("document.documentElement.outerHTML").ToString
RenderingDone = True
RemoveHandler view.LoadingFrameFailed, Nothing
view.Dispose()
view = Nothing
session.Dispose()
session = Nothing
End If
End Sub
AddHandler view.LoadingFrameFailed, Sub(s, e)
If e.IsMainFrame Then
Me.RenderedHTML = ""
RenderingDone = True
RemoveHandler view.LoadingFrameFailed, Nothing
view.Dispose()
view = Nothing
session.Dispose()
session = Nothing
End If
End Sub
view.Source = URL.ToUri
End Sub
End Class
我在多线程 winforms 应用程序中使用上面的 Browser
class,它是一个网络抓取工具,如下所示:
Dim A as New Browser
Dim ResultA As String = A.GetRenderedHTML("http://google.com")
Dim B as New Browser
Dim ResultB As String = B.GetRenderedHTML("http://google.com")
A.GetRenderedHTML
有效,但 B.GetRenderedHTML
在之后直接调用时失败。 IE。只有 Browser
class 的第一个实例有效。
问题是你在第二次调用WebCore.QueueWork(Sub() RenderHTML(URL))
之前没有设置RenderingDone = false
。
感谢所有评论的人。
我相信我终于想出了一个适用于 Awesomium.Net
的线程安全包装器 class
我已经在 github 上发布了最终的工作源代码。您可以在下面的 link 查看:
https://github.com/dj-nitehawk/ThreadSafeAwesomium.Net/blob/master/Browser.vb
在这里为感兴趣的人留下这个答案:-)
干杯!
要测试此 class 请从 here 安装 Awesomium.Net sdk 并将对 Awesomium.Core.dll
的引用添加到 visual studio 项目。
我遇到的问题 class 是,它只适用于第一个实例。随后的实例不会导致在 WebView
对象上触发适当的事件,并且在以后的实例中不会返回任何结果。我已经为此苦苦挣扎了好几天,似乎无法弄清楚为什么它只能工作一次。请帮忙...
Imports Awesomium.Core
Public Class Browser
Private Shared Thread As Threading.Thread
Private Shared CoreIsRunning As Boolean = False
Dim RenderedHTML As String = ""
Dim RenderingDone As Boolean = False
Private Shared Sub AwesomiumThread()
WebCore.Initialize(New WebConfig With {.LogLevel = LogLevel.None}, False)
WebCore.Run(Sub(s, e)
CoreIsRunning = True
End Sub)
End Sub
Shared Sub DeInit()
WebCore.Shutdown()
Thread = Nothing
End Sub
Shared Sub Init()
If Not WebCore.IsInitialized And IsNothing(Thread) Then
Thread = New Threading.Thread(AddressOf AwesomiumThread)
Thread.Start()
End If
End Sub
Sub New()
Init()
End Sub
Function GetRenderedHTML(URL As String) As String
Do Until CoreIsRunning
Task.Delay(300).Wait()
Loop
WebCore.QueueWork(Sub() RenderHTML(URL))
Dim startTime As Date = Date.UtcNow
Do Until RenderingDone = True
If Date.UtcNow.Subtract(startTime).TotalSeconds >= 30 Then
'view.Dispose()
'view = Nothing
'session.Dispose()
'session = Nothing
Exit Do
End If
Task.Delay(1000).Wait()
Loop
If String.IsNullOrEmpty(RenderedHTML) Then
Throw New Exception("Rendering failed!")
End If
Return Me.RenderedHTML
End Function
Private Sub RenderHTML(URL As String)
Dim session As WebSession = WebCore.CreateWebSession(New WebPreferences With {.LoadImagesAutomatically = False, .LocalStorage = False, .Plugins = False, .RemoteFonts = False, .WebAudio = False, .CanScriptsOpenWindows = False, .DefaultEncoding = "utf-8"})
Dim view As WebView = WebCore.CreateWebView(1100, 600, session, WebViewType.Offscreen)
RenderingDone = False
AddHandler view.LoadingFrameComplete, Sub(s, e)
If e.IsMainFrame Then
Me.RenderedHTML = view.ExecuteJavascriptWithResult("document.documentElement.outerHTML").ToString
RenderingDone = True
RemoveHandler view.LoadingFrameFailed, Nothing
view.Dispose()
view = Nothing
session.Dispose()
session = Nothing
End If
End Sub
AddHandler view.LoadingFrameFailed, Sub(s, e)
If e.IsMainFrame Then
Me.RenderedHTML = ""
RenderingDone = True
RemoveHandler view.LoadingFrameFailed, Nothing
view.Dispose()
view = Nothing
session.Dispose()
session = Nothing
End If
End Sub
view.Source = URL.ToUri
End Sub
End Class
我在多线程 winforms 应用程序中使用上面的 Browser
class,它是一个网络抓取工具,如下所示:
Dim A as New Browser
Dim ResultA As String = A.GetRenderedHTML("http://google.com")
Dim B as New Browser
Dim ResultB As String = B.GetRenderedHTML("http://google.com")
A.GetRenderedHTML
有效,但 B.GetRenderedHTML
在之后直接调用时失败。 IE。只有 Browser
class 的第一个实例有效。
问题是你在第二次调用WebCore.QueueWork(Sub() RenderHTML(URL))
之前没有设置RenderingDone = false
。
感谢所有评论的人。
我相信我终于想出了一个适用于 Awesomium.Net
的线程安全包装器 class我已经在 github 上发布了最终的工作源代码。您可以在下面的 link 查看:
https://github.com/dj-nitehawk/ThreadSafeAwesomium.Net/blob/master/Browser.vb
在这里为感兴趣的人留下这个答案:-)
干杯!