I am trying to spawn a new thread from an ASP page written in VB.NET, on .NET 3.5.
The page allows a user to upload files and then processes the files into the database. As the processing can take a while, I want to upload them, spawn the processing onto a new thread, and then when it completes send the user a notification through our database-driven notification module in the system.
I've tried a couple different examples I've found online, but they don't seem to work. There is no error thrown, but it never seems to actually launch the processing code on a new thread either.
Here is my submittal code in the web page:
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
Try
If Not (file1.HasFile Or file2.HasFile Or file3.HasFile Or file4.HasFile Or file5.HasFile) Then
AddErrorMessage("Please specify at least one file.")
Else
Dim l = New List(Of InventoryUploads.File)
If file1.HasFile Then l.Add(New InventoryUploads.File With {.Name = file1.FileName, .Content = file1.FileContent})
If file2.HasFile Then l.Add(New InventoryUploads.File With {.Name = file2.FileName, .Content = file2.FileContent})
If file3.HasFile Then l.Add(New InventoryUploads.File With {.Name = file3.FileName, .Content = file3.FileContent})
If file4.HasFile Then l.Add(New InventoryUploads.File With {.Name = file4.FileName, .Content = file4.FileContent})
If file5.HasFile Then l.Add(New InventoryUploads.File With {.Name = file5.FileName, .Content = file5.FileContent})
InventoryUploads.ProcessFiles(l, Session.UserIdent, chkRcvOverwrite.Checked)
NewRow("Your files have been queued and are being processed. You will be sent a notification when they are completed.")
End If
Catch ex As Exception
LogEx(ex)
NewRow("There was an error queueing your files." & BR & ex.Message)
End Try
End Sub
From a UI point of view, this all works, the page posts the files, and it shows the user the message about "your files have been queued".
The call to InventoryUploads.ProcessFiles
is an encapsulation function in front of the threading code, which is all contained in the InventoryUploads
module (following):
Imports System.Threading
Imports System.Threading.Tasks
Public Module InventoryUploads
Public Structure File
Private pName As String
Private pContent As IO.Stream
Private pProcessed As Boolean
Public Property Name As String
Get
Return pName
End Get
Set(value As String)
pName = value
End Set
End Property
Public Property Content As IO.Stream
Get
Return pContent
End Get
Set(value As IO.Stream)
pContent = value
End Set
End Property
Public Property Processed As Boolean
Get
Return pProcessed
End Get
Set(value As Boolean)
pProcessed = value
End Set
End Property
End Structure
Public Sub ProcessFiles(files As List(Of File), userident As String, receivingsOverwrite As Boolean)
Try
Dim params = Array.CreateInstance(GetType(Object), 3)
params(0) = files
params(1) = userident
params(2) = receivingsOverwrite
'// Threading Method 1
Dim pts = New ParameterizedThreadStart(AddressOf ThreadedProcessFiles)
Dim thd = New Thread(pts)
thd.IsBackground = True
thd.Start(params)
'// Threading Method 2
'ThreadPool.QueueUserWorkItem(AddressOf ThreadedProcessFiles, params)
'// Threading Method 3
Dim f As Func(Of Integer) = Function() ThreadedProcessFiles(params)
Task.Factory.StartNew(f)
Catch ex As Exception
IO.File.WriteAllText("C:\idwherenet.log", ex.Message)
Throw
End Try
End Sub
''' <summary>
'''
''' </summary>
''' <param name="params">exepcts params to contain 3 objects,
''' 1) type List(Of File),
''' 2) string userident to notify on finish
''' 3) boolean whether receivings should overwrite</param>
''' <remarks></remarks>
Private Function ThreadedProcessFiles(params() As Object) As Boolean
IO.File.WriteAllText("C:\mylog.log", "hello ThreadedProcessFiles?")
'Log("threadedprocessfiles: got here")
Dim files As List(Of File), uident As String = "", rcvovr As Boolean
Try
files = params(0)
uident = CStr(params(1))
rcvovr = CBool(params(2))
If files.Count = 0 Then
SendNotification(NotificationTypes.SYS, uident, "No files provided for inventory upload; nothing processed.")
Exit Sub
End If
For Each f In files
f.Processed = False
If f.Content.Length = 0 Then Continue For
'// process the file here....
f.Processed = True
Next
SendNotification(NotificationTypes.SYS, uident, "Inventory upload processing completed.")
Return True
Catch ex As Exception
'LogEx(ex)
'Log(ex.Message, ex.ToString)
If Not uident.IsEmpty Then SendNotification(NotificationTypes.SYS, uident, "Inventory upload processing encountered an error. " & ex.Message, ex.ToString)
Return False
End Try
End Sub
End Module
In the ProcessFiles
sub, you can see the three different methods I have tried to spawn the thread, including a NuGet backport of the Task Parallel Library... neither works. I have confirmed that is is making it into the ProcessFiles
sub, and the code to spawn the thread is not throwing any errors... it just never actually calls the ThreadedProcessFiles
function.
Any ideas?
UPDATE: Oh, actually, the NuGet package DOES seem to be working, FINALLY! It just doesn't write out to the file (context/security/impersonation permissions I guess). Now I can finally move on!