C# 为什么这种线程方法不起作用?

C# 为什么这种线程方法不起作用?,c#,.net,asp.net,vb.net,multithreading,C#,.net,Asp.net,Vb.net,Multithreading,我在ASP.NET应用程序中遇到了一个严重的线程问题。出于某种原因,当我在请求线程中运行代码时,一切都按预期进行。但是当我在一个单独的线程中运行它时,什么都不会发生。 这可以通过分别使用三个标志“on”、“off”和“larma”调用下面的处理程序来验证——在前两种情况下,一切都正常,但在后一种情况下,什么都不发生 我做错了什么? 在web项目中,我有一个通用处理程序,其代码如下: If task = "on" Then Alarm.StartaLarm(personId) co

我在ASP.NET应用程序中遇到了一个严重的线程问题。出于某种原因,当我在请求线程中运行代码时,一切都按预期进行。但是当我在一个单独的线程中运行它时,什么都不会发生。
这可以通过分别使用三个标志“on”、“off”和“larma”调用下面的处理程序来验证——在前两种情况下,一切都正常,但在后一种情况下,什么都不发生

我做错了什么?

在web项目中,我有一个通用处理程序,其代码如下:

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
报警
类具有以下方法:

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
更新/澄清:调用线程版本时,我仍然会收到客户端的预期响应-没有错误消息

我还在上面的代码中包含了一个被遗忘的方法

更新2: @Henk,不幸的是我没有调试的能力,因为这个问题只出现在我们的sharp服务器上,它没有安装Visual Studio,也不允许远程调试

但是,
SendSMS
方法会向我的手机发送文字信息,并且文字信息网络服务和我的手机都同意在呼叫“开”或“关”时发送信息,而不是在呼叫“larma”时发送信息

由于我知道整个链处理程序->
StartaLarm
->
SandSMS(真/假)
适用于“开”和“关”,因此我必须假设故障发生在处理程序->
Larma
->
Larma\u线程
的某个地方,因此是一个线程问题

更新3:@Vadmyst,在将您的代码转换为VB.NET(这也不是我最喜欢的,但这个项目需要它…)并对其进行修改以进行编译后,我得出了以下结论(尽管我不能100%肯定它仍然意味着相同的东西…):


没有成功-我有与上面相同的结果=(

SendSMS是否依赖于任何ASP.NET内部组件? 尝试使用线程池启动Larma_线程

我不是VB大师,我将尝试在C上使用ThreadPool编写示例#


SendSMS是否依赖于任何ASP.NET内部组件? 尝试使用线程池启动Larma_线程

我不是VB大师,我将尝试在C上使用ThreadPool编写示例#


日志是你在这里的朋友。如果你正在发送短信,你当然应该在尝试之前和尝试之后(或失败之后)都进行日志记录

对于这个特殊问题,我建议您在启动线程之前和之后添加日志记录(或者将任务提交到线程池)。基本上,您输入的日志越多(当然是暂时的),您就越了解正在发生的事情


重要的是,请确保您记录引发的任何异常。您也应该查看IIS日志,以查看是否有任何异常记录在那里。

日志记录是您在这里的朋友。如果您发送短信,您当然应该在尝试前和尝试后(或失败后)进行日志记录

对于这个特殊问题,我建议您在启动线程之前和之后添加日志记录(或者将任务提交到线程池)。基本上,您输入的日志越多(当然是暂时的),您就越了解正在发生的事情


重要的是,请确保记录抛出的任何异常。您还应该查看IIS日志,以查看是否有任何异常记录在那里。

您在辅助线程上下文中的
SandSMS
中有一个异常,该异常从
StartaLarm
调用,从
Larma_Thread
调用多线程应用程序中的行为是次线程异常的强烈指示。首先想到的是,与web应用程序的非请求线程不同,非请求线程无权访问
请求
上下文
会话
等在次线程的上下文中,从
StartaLarm
调用的
SandSMS
中的异常从
Larma_线程
调用。“什么也不发生”多线程应用程序中的行为是次线程异常的强烈迹象。首先想到的是,与web应用程序的非请求线程不同,非请求线程无权访问
请求
上下文
会话
等等。

我不知道如果这一点很重要,但您是参数化线程启动的代理,则该线程启动的原型不正确。应如下所示:

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

公共委托子参数化线程启动(obj作为对象)
您使用int输入类型定义了它,但不确定这里会发生什么

有关更多信息,请参阅MSDN上的这篇文章:


我不知道这是否重要,但您代表的参数化线程启动不是正确的原型。它应该如下所示:

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

公共委托子参数化线程启动(obj作为对象)
您使用int输入类型定义了它,但不确定这里会发生什么

有关更多信息,请参阅MSDN上的这篇文章:


该澄清说明线程版本正在工作???@Henk:不-不工作,只是没有给出任何错误。正如您在代码中看到的,我启动了一个不同的线程来执行任务,然后将一个字符串返回给客户端。返回了字符串,但未执行任务。很抱歉,没有更清楚地说明这一点。您是否删除了字符串要了解2个SendSMS调用是否实际执行?处理程序是否在线程退出之前加入线程?如果您在StartAlarm&StopAlarm中加入一些日志,您看到了吗?如果您在dev box上运行它并登录SendSMS,会怎么样?@danio:不,处理程序在线程返回到客户端之前不会加入线程,并且(我假设)在单独的线程中执行此操作的唯一原因是我不想等待单独的线程
<ComVisibleAttribute(False)>
Public Delegate Sub ParameterizedThreadStart ( obj As Object )