收录日期:2019/06/20 01:20:10 时间:2010-06-25 02:26:58 标签:c#,.net,asp.net,vb.net,multithreading

I have a wierd problem with threading in an ASP.NET application. For some reason, when I run the code in the request thread, everything works as expected. But when I run it in a separate thread, nothing happens.
This is verified by calling the below handler with the three flags "on", "off" and "larma" respectively - in the two first cases everything works, but in the latter nothing happens.

What am I doing wrong here?

In the web project I have a generic handler with the following code:

If task = "on" Then
    Alarm.StartaLarm(personId)
    context.Response.Write("Larmet är PÅ")
ElseIf task = "off" Then
    Alarm.StoppaLarm(personId)
    context.Response.Write("Larmet är AV")
ElseIf task = "larma" Then
    Alarm.Larma(personId)
    context.Response.Write("Larmar... (stängs av automagiskt)")
Else
    context.Response.Write("inget hände - task: " & task)
End If

The Alarm class has the following methods:

Public Shared Sub Larma(ByVal personId As Integer)
    Dim thread As New System.Threading.Thread(New ParameterizedThreadStart(AddressOf Larma_Thread))
    thread.Start(personId)
End Sub

Private Shared Sub Larma_Thread(ByVal personId As Integer)
    StartaLarm(personId)
    Thread.Sleep(1000 * 30)
    StoppaLarm(personId)
End Sub

Public Shared Sub StartaLarm(ByVal personId As Integer)
    SandSMS(True, personId)
End Sub

Public Shared Sub StoppaLarm(ByVal personId As Integer)
    SandSMS(False, personId)
End Sub

Public Shared Sub SandSMS(ByVal setOn As Boolean, ByVal personId As Integer)
    ...
End Sub

UPDATE/CLARIFICATION: I still get the expected response to the client - no error messages - when calling the threaded version.

I also included a forgotten method in the code above.

Update 2: @Henk, Unfortunately I don't have the ability to debug, because this problem arises only on our sharp server, which doesn't have Visual Studio installed and doesn't allow remote debugging.

However, the SendSMS method sends text messages to my phone, and both the text message web service and my phone agrees that the messages are sent when calling "on" or "off", but not when calling "larma".

Since I know that the entire chain Handler->StartaLarm->SandSMS(True/False) works for "on" and "off", I must assume that the failure occurs somewhere in Handler->Larma->Larma_Thread, and thus is a threading issue.

Update 3: @Vadmyst, after converting your code to VB.NET (which is not my favourite of the two either, but this project requires it...) and modifying it to compile, I arrived at the following (although I'm not 100% certain it still means the same thing...):

ThreadPool.QueueUserWorkItem(New WaitCallback(Function(p As Integer) Larma_Thread(p)))

No success - I have the same results as above... =(

You have an exception in SandSMS called from StartaLarm called from Larma_Thread in the context of a secondary thread. The "nothing happens" behaviour in a multi-threaded application is a strong indication of exception in a secondary thread. The first thing that comes to mind, that is different in a non-request thread in a web application, is that a non-request thread does not have access to things such as current HttpContext and Session.

Logging is your friend here. If you're sending an SMS, you should certainly be logging before you try and after you've done it (or failed to do it).

For this particular issue, I suggest you add logging before and after you start the thread (or submit the task to the thread pool) too. Basically, the more logging you put in (temporarily, of course) the more idea you'll have what's going on.

Importantly, make sure you log any exceptions which are thrown. You should look in the IIS logs as well, to see if there are any exceptions logged there.

Does SendSMS rely on any ASP.NET internals stuff? Try using ThreadPool for starting Larma_Thread.

I'm not a VB guru and will try to write the sample with ThreadPool on C#

public static void Larma(int personId)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(
            delegate(object unused)
            {
                try
                {
                    Larma_Thread(personId);
                }
                catch { /*log here */}
            }), personId);
    }

I don't know if this is important but you're delegate for the parameterized thread start is not of the correct prototype. It should be as follows:

<ComVisibleAttribute(False)>
Public Delegate Sub ParameterizedThreadStart ( obj As Object )

You have it defined with an input type of int, not sure what would happen here.

See this article on MSDN for more information:

ParameterizedThreadStart Delegate