Вопрос

Интересно, может ли кто-нибудь мне помочь - я программирую на VB.Net в течение длительного времени, но мне редко приходилось выполнять много потоков в ASP.Net.

Я пытаюсь делать "скриншоты" веб-сайтов, используя браузер в памяти.Затем эти изображения регистрируются в базе данных и записываются в локальную файловую систему.

Когда я запускаю его на своем локальном сервере, все работает нормально.Когда я запускаю его в среде общего хостинга, все в порядке до тех пор, пока я не создам поток.join, в этот момент либо целевой поток немедленно завершается, либо зависает (ни от одного из потоков не поступает дополнительная информация о протоколировании).Я приложил журнал ниже

Ключевой код также прилагается, но вкратце он делает:

Для каждого URL-адреса запустите новый поток и thread.присоединитесь к нему.Новый поток загрузит браузер и начнет навигацию.затем он будет отключен до завершения загрузки браузера, прежде чем вернуть сгенерированное растровое изображение (следующий шаг).

По завершении загрузки браузера срабатывает событие.Обработчик захватывает растровое изображение из браузера и записывает его в локальный файл.

Я немного погуглил и не могу найти много связанной информации - я обнаружил распространенные проблемы с общим хостингом и убедился, что они решены (например, разрешение частично доверенных абонентов, подписание сборок и т.д.)

Я был бы признателен, если бы кто-нибудь, обладающий знаниями по этой теме, был достаточно любезен, чтобы указать мне правильное направление.

Большое спасибо

ПРИМЕЧАНИЕ:Я знаю, что в настоящее время это будет очень медленно, поскольку он обрабатывает изображения последовательно - но пока я не смогу заставить его работать в одном потоке, у меня нет шансов заставить его работать в нескольких потоках.

Это в значительной степени скомкано из примеров кода, и я даже не начал приводить его в порядок / организовывать лучше, так что приношу извинения за немного беспорядочный код.

Public Function GetWebsiteImage(ByVal URL As String, Optional ByVal BrowserWidth As Integer = 1280, Optional ByVal BrowserHeight As Integer = 1024) As Bitmap
    LogIt(String.Format("Webshot {1}: {0}", "Getting Image", id))
    _URL = URL
    _BrowserHeight = BrowserHeight
    _BrowserWidth = BrowserWidth

    Dim T As Thread
    T = New Thread(New ThreadStart(AddressOf GenerateImage))

    T.SetApartmentState(ApartmentState.STA)
    'T.IsBackground = True
    LogIt(String.Format("Webshot {1}: {0}", "Starting Thread", id))
    T.Start()

    '*** THIS IS THE LAST LOG ENTRY I SEE ***
    LogIt(String.Format("Webshot {1}: {0}", "Joining Thread", id))
    T.Join()

    Return _Bitmap
End Function

Friend Sub GenerateImage()
    LogIt(String.Format("Webshot {1}: {0}", "Instantiating Web Browser", id))
    Dim _WebBrowser As New WebBrowser()
    _WebBrowser.ScrollBarsEnabled = False
    LogIt(String.Format("Webshot {1}: {0}", "Navigating", id))
    _WebBrowser.Navigate(_URL)
    AddHandler _WebBrowser.DocumentCompleted, AddressOf WebBrowser_DocumentCompleted
    'AddHandler _WebBrowser.
    While _WebBrowser.ReadyState <> WebBrowserReadyState.Complete
        Application.DoEvents()
    End While
    LogIt(String.Format("Webshot {1}: {0}", "Disposing", id))
    _WebBrowser.Dispose()
End Sub

Private Sub WebBrowser_DocumentCompleted(ByVal sender As Object, ByVal e As WebBrowserDocumentCompletedEventArgs)
    LogIt(String.Format("Webshot {1}: {0}", "Document load complete", id))
    Dim _WebBrowser As WebBrowser = DirectCast(sender, WebBrowser)
    _WebBrowser.ClientSize = New Size(Me._BrowserWidth, Me._BrowserHeight)
    _WebBrowser.ScrollBarsEnabled = False
    _Bitmap = New Bitmap(_WebBrowser.Bounds.Width, _WebBrowser.Bounds.Height)
    _WebBrowser.BringToFront()
    _WebBrowser.DrawToBitmap(_Bitmap, _WebBrowser.Bounds)
    _PageTitle = _WebBrowser.DocumentTitle
    LogIt(String.Format("Webshot {1}: {0}", "About to capture bitmap", id))
    _Bitmap = DirectCast(_Bitmap.GetThumbnailImage(_BrowserWidth, _BrowserHeight, Nothing, IntPtr.Zero), Bitmap)
    LogIt(String.Format("Webshot {1}: {0}", "Bitmap captured", id))
End Sub

и записи в журнале, которые я вижу:

2010 01 19 02:21:01 > Starting Process
2010 01 19 02:21:01 > Capture 229 Processing: http://www.obfuscated.com/
2010 01 19 02:21:01 > Capture 229 Found capture db record
2010 01 19 02:21:01 > Webshot f7710f41-cac0-4ed1-93df-020620257c91: Instantiated
2010 01 19 02:21:01 > Capture 229 Requesting image
2010 01 19 02:21:01 > Webshot f7710f41-cac0-4ed1-93df-020620257c91: Getting Image
2010 01 19 02:21:01 > Webshot f7710f41-cac0-4ed1-93df-020620257c91: Starting Thread
2010 01 19 02:21:01 > Webshot f7710f41-cac0-4ed1-93df-020620257c91: Joining Thread
Это было полезно?

Решение

Когда вы запускаете его на своем локальном сервере, вы имеете в виду ASP.NET персональный веб-сервер или локальную установку IIS?Первый даже не сравним с IIS, потому что он работает как интерактивное приложение Windows, тогда как со вторым вы будете работать как служба, у которой может не быть пользовательского интерфейса, а поведение потоков строго регулируется IIS.

Вы могли бы попробовать установить aspcompat="true" в директиве Page, но, скорее всего, хостинговая компания настроила пинг рабочего процесса IIS, который завершит потоки, которые не отвечают в течение определенного периода времени.

Суть в том, что элемент управления WebBrowser (и элемент управления SHDocVw ActiveX, который он оборачивает) не предназначен для работы в неинтерактивном сервисном процессе, и вам, скорее всего, придется подниматься в гору, пытаясь заставить его работать.Однако, к сожалению, я не знаю ни одной более безопасной альтернативы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top