Thread.Join в среде общего хостинга - PullRequest
2 голосов
/ 19 января 2010

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

Я пытаюсь сделать "скриншоты" сайтов с помощью браузера в памяти. Эти изображения затем регистрируются в БД и записываются в локальную файловую систему.

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

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

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

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

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

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

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

NB. Я знаю, что в настоящее время он будет очень медленным, поскольку он обрабатывает изображения последовательно - но пока я не смогу заставить его работать в одном потоке, у меня нет шансов заставить его работать в нескольких потоках.

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

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

1 Ответ

1 голос
/ 19 января 2010

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

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

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

...